Management API
Create, rotate and revoke project keys, edit Directives, add webhooks and read the audit log from Terraform, CI or your own platform, with a management key.
Management keys
The management API takes a management key, created by an owner or admin under Team → Management keys in the console. It starts with ib_mgmt_, belongs to the team rather than a project, and is shown once. It can't call models or read usage: inference endpoints answer it with 401 invalid_api_key. A project key (ib_live_, ib_test_) on a management endpoint gets 403 policy_denied. The API never creates management keys, so a leaked one can't make more; revoke it in the console and its next call is refused.
curl https://api.inferencebureau.com/v1/keys \
-H "Authorization: Bearer $IB_MANAGEMENT_KEY"Everything is scoped to the key's team. An id from another team answers 404 not_found, the same as an id that doesn't exist. Times are ISO 8601 in UTC.
Endpoints
| Endpoint | What it does |
|---|---|
| GET /v1/keys | List project keys, with last use and expiry |
| POST /v1/keys | Create a key in a project and environment, optionally with an expiry and its own Directives |
| GET /v1/keys/{id} | One key |
| PATCH /v1/keys/{id} | Rename a key, or change its expiry or its permissions |
| DELETE /v1/keys/{id} | Revoke a key |
| POST /v1/keys/{id}/pause | Stop a key until it is resumed |
| POST /v1/keys/{id}/resume | Make a paused key work again |
| POST /v1/keys/{id}/rotate | A new secret, with the old one working for an overlap |
| GET /v1/projects | Projects and their environments, for ids |
| GET …/directives | A project's, environment's or key's Directives |
| PATCH …/directives | Change them, optimistic on policy_version |
| GET /v1/team/directives | The team's own Directives, the ceiling for every project |
| PATCH /v1/team/directives | Change them, with a key that has the Team Directives permission |
| GET /v1/webhooks | The team's webhook endpoints |
| POST /v1/webhooks | Add an endpoint |
| PATCH /v1/webhooks/{id} | Change an endpoint's URL, events or project |
| POST /v1/webhooks/{id}/rotate | A new signing secret, with an overlap |
| GET /v1/webhooks/{id}/deliveries | An endpoint's deliveries, a page at a time |
| POST /v1/webhooks/{id}/deliveries/{delivery_id}/replay | Send a delivery again |
| DELETE /v1/webhooks/{id} | Remove an endpoint |
| GET /v1/audit | The team's audit log, newest first |
Secrets
A key's plaintext is in the response to POST /v1/keys and POST /v1/keys/{id}/rotate only, as secret; a webhook's signing secret only in the response to POST /v1/webhooks and POST /v1/webhooks/{id}/rotate. They are stored hashed or encrypted and never returned again. Other responses show key_hint, the prefix and last four characters.
Rotation
Rotating a key creates a new key, with a new id and secret, that has the old key's name, project, environment, Directives, permissions, mixed-model mode and expiry. The old key keeps working for overlap_seconds (default 24 hours, at most 7 days), then expires; 0 revokes it at once. Deploy the new secret within the overlap. A key-level budget carries on: the new key spends from the same day and month as the old one, whatever the old key spends during the overlap counts once against both, and requests the old key started before the rotation settle there too.
Directives and policy_version
Each level's Directives carry a policy_version. A change names the version it was based on; if someone changed them since, in the console or the API, the change is refused with 409 version_conflict and nothing is written. Read again, reapply, retry. Directives are validated exactly as the console validates them, and each level can only tighten the one above (see Directives).
Team Directives
Any management key can read the team's own Directives with GET /v1/team/directives. Changing them takes a key created with the Team Directives permission, a box ticked under Team → Management keys when the key is made and shown on its row; it is off by default, a rotated key keeps it, and without it PATCH /v1/team/directives answers 403 policy_denied. The team's Directives are the ceiling every project, environment and key composes under, so a key that can change them can loosen everything at once; one that can't can at most loosen the levels below, which stay inside the team's limits. Give the permission to the one tool that manages the ceiling, and keep the keys you hand to CI or customers' provisioning without it. The rules are the console's team save: the same validation, policy_version check and policy.update audit event (on organization:<id>), and only here can alerts.lowBalanceUsd be set.
Idempotent retries
POST /v1/keys, POST /v1/keys/{id}/rotate and POST /v1/webhooks take an Idempotency-Key header, as the inference API does. Send one generated per operation, and reuse it only to retry that operation, such as after a timeout:
- Same key, same body, within 24 hours:
409 result_not_replayable, and nothing new is made. The body names the original request (original_request_id, also theX-Original-Request-IDheader) and what it made (original_idand its path inresource). The secret isn't in it: secrets are shown once and not kept. If the first response was lost, rotate the key, or remove the endpoint and add it again. - Same key, different body (another key's rotation counts):
409 idempotency_conflict. - Two calls with the same key at once: one makes the resource, the other waits for it and gets the
409.
Keys are scoped to your team and the endpoint. Only a call that made something is remembered, so a refused one (a 400 or 404) can be retried with the same key once fixed.
Audit log
Every change writes the same audit event the console writes (key.create, key.update, key.rotate, key.revoke, policy.update, webhook.add, webhook.update, webhook.rotate_secret, webhook.replay, webhook.remove), with the management key as the actor (key:<id>). Read the log with GET /v1/audit, or in the console under Settings → Audit log, where owners and admins can download it as CSV. Events are kept for as long as the team exists.
Rate limits
120 requests a minute per management key, and 60 changes a minute per team across all its management keys. Over either, the API answers 429 rate_limit_exceeded with Retry-After.
Errors
Errors have the usual shape. 400 invalid_request names the field at fault in param; 404 not_found covers ids outside the team; 409 version_conflict is a stale policy_version; 409 result_not_replayable and idempotency_conflict are retries with an Idempotency-Key; 413 payload_too_large is a body over 64 KiB.