> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opper.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Management API

> Provision projects and runtime API keys programmatically, from CI or infrastructure-as-code.

The Management API is the provisioning surface for your organization. Creating a
project, minting a runtime key for it, and retiring both are the things you would
otherwise do by hand in the platform UI — here they are HTTP endpoints, so
onboarding a service or tearing down a stale environment can live in CI or
Terraform instead of a runbook.

It is a control-plane API: it manages the containers your model calls run in, not
the calls themselves. Sending a prompt still goes through the
[v3 API](/v3-api-reference/compatibility/chat-completions) with a runtime key.

<Note>
  The Management API is available on selected plans. If your organization's plan
  does not include it, every endpoint answers `403` with the current and allowed
  plans in the body.
</Note>

## Authentication

The Management API uses its own credential — a **management key**, prefixed
`op-mak-`. Mint one in the platform UI under **Settings → API keys**, then send it
as a bearer token:

```bash theme={null}
curl https://api.opper.ai/management/v1/projects \
  -H "Authorization: Bearer $OPPER_MANAGEMENT_API_KEY"
```

A runtime `op-…` key is not accepted here — it will be rejected with `403`. The
two credentials are deliberately different things:

|            | Runtime key (`op-…`)          | Management key (`op-mak-…`)        |
| ---------- | ----------------------------- | ---------------------------------- |
| Used for   | Model calls on the v3 API     | Provisioning on the Management API |
| Bound to   | A single project              | The whole organization             |
| Created by | The Management API, or the UI | The platform UI                    |
| Carries    | No scopes                     | An explicit scope list             |

<Warning>
  A management key can create and delete projects across your entire
  organization. Store it as a secret in your CI provider — never in application
  config alongside runtime keys, and never in a client.
</Warning>

## Scopes

Every management key carries an explicit list of scopes, chosen when you mint it.
A request whose key lacks the scope an endpoint requires is rejected with `403`
and a `required_scope` field naming what was missing.

| Scope             | Grants                                            |
| ----------------- | ------------------------------------------------- |
| `projects:read`   | List and fetch projects                           |
| `projects:write`  | Create and update projects                        |
| `projects:delete` | Delete projects, and with them their runtime keys |
| `apikeys:read`    | List a project's runtime keys (prefixes only)     |
| `apikeys:write`   | Mint and delete runtime keys                      |

Grant the narrowest set that does the job. A CI pipeline that only rotates keys
needs `apikeys:write` and nothing else.

## Response shape

Every response is an envelope with `meta` and `data`. Single resources leave
`meta` empty; collections use it for `total_count`.

```json theme={null}
{
  "meta": { "total_count": 2 },
  "data": [
    { "uuid": "…", "name": "checkout-service", "description": "", "created_at": "2026-08-01T09:12:44Z" }
  ]
}
```

## Provision a project and a runtime key

The common pipeline is two calls: create the project, then mint a key inside it.

<Steps>
  <Step title="Create the project">
    ```bash theme={null}
    curl -X POST https://api.opper.ai/management/v1/projects \
      -H "Authorization: Bearer $OPPER_MANAGEMENT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name": "checkout-service"}'
    ```

    Project names are unique within an organization — reusing one returns `409`.
    The response carries the project `uuid` you need for the next call.
  </Step>

  <Step title="Mint a runtime key inside it">
    ```bash theme={null}
    curl -X POST https://api.opper.ai/management/v1/projects/$PROJECT_UUID/api-keys \
      -H "Authorization: Bearer $OPPER_MANAGEMENT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name": "ci-deploy"}'
    ```

    <Warning>
      The full `op-…` key is returned **once**, in this response, and is never
      retrievable again. Write it to your secret store in the same step that
      creates it. Listing keys later returns only their prefixes.
    </Warning>
  </Step>

  <Step title="Use it for model calls">
    The minted key is an ordinary runtime key, scoped to that project. Hand it to
    the service as `OPPER_API_KEY` and call the v3 API with it.
  </Step>
</Steps>

## Lifecycle notes

* **Updates are partial.** `PATCH` a project with `name`, `description`, or both;
  omit a field to leave it unchanged, and send `"description": null` to clear it.
  A body with neither field is rejected rather than treated as a no-op.
* **Deleting a project deletes its keys.** The project is soft-deleted, but every
  runtime key bound to it is permanently destroyed and stops working immediately.
* **Retention is not set here.** It is a control-plane rule — see
  [data retention](/control-plane/rules/retention).

## Revoke a leaked management key

If a management key is exposed, disable it with the key itself:

```bash theme={null}
curl -X POST https://api.opper.ai/management/v1/management-keys/_self/disable \
  -H "Authorization: Bearer $LEAKED_KEY"
```

Possession of the token is the authorization — no scope is required, and it works
regardless of your plan, so a leaked key can always be shut off. This disables the
key the request authenticated with and every token issued under it.

## Endpoints

<CardGroup cols={2}>
  <Card title="Projects" icon="folder" href="/v3-api-reference/management/list-projects">
    List, create, fetch, update, and delete projects.
  </Card>

  <Card title="API keys" icon="key" href="/v3-api-reference/management/list-api-keys">
    List, mint, and delete a project's runtime keys.
  </Card>
</CardGroup>
