Graine AI

Revoke an API key

Revoke an API key.

Revoke an API key.

Requires the keys:write scope. The key is DEACTIVATED rather than deleted: status becomes inactive and authentication refuses it from the moment the 30-second auth cache rolls, but an account admin can still undo a mistake.

The endpoint refuses to revoke the key making the request, so an integration cannot lock itself out mid-call.

Only keys belonging to the caller's own organization are even considered: the organization filter is applied before any key_id is computed, so a key id obtained elsewhere cannot select another tenant's record. A key id that does not exist in this organization returns 404, never 403 — the existence of another tenant's key is not something this API confirms.

Revoking an already-inactive key is a no-op that returns its existing revocation timestamp, so a retried request is safe.

Errors: 401, 403 (missing scope or wrong organization), 404 (no such key in this organization), 409 (the key store lock is held, or the caller tried to revoke its own key), 429, 503.

Rate limit: 1000 requests per minute per organization (bucket default). Exceeding it returns 429 with Retry-After; the X-RateLimit-* response headers report your remaining allowance on every call.

DELETE
/v2/api-keys/{key_id}
/v2/api-keys/key_1a2b3c4d5e6f7890

The Authorization access token

Authorization

Authorization
Required
Bearer <token>

Your Graine API key. Create one in the dashboard under Developers, or via POST /v2/api-keys. Send it as Authorization: Bearer <key>.

In: header

Path Parameters

key_id
Required
Key Id

The 'key_...' id from GET /v2/api-keys.

Query Parameters

organization_idOrganization Id

Optional; must match the key's organization.

Response Body

200

The key's new state. Revocation is a deactivation, not an erasure.

key_id
Required
Key Id

The key that was revoked.

status
Required
Status

Always 'inactive' once revoked.

revoked
Required
Revoked

Always true; a failure is reported as an error envelope.

revoked_atRevoked At | null

When the revocation was recorded.

401

1100 — missing, unknown or inactive API key. 1101 — a browser session token was presented instead of an API key.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

403

1102 — the key is valid but lacks the scope this endpoint requires, or names another organization. GET /v2/scopes reports what a key holds.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

404

1200 — no such resource in your organization. A resource belonging to another organization answers 404, never 403.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

422

1001 — the body or query failed validation; the message names the first offending field.

error
Required
integer

Stable integer code from the error table. Branch on this, not on the message.

message
Required
string

One human-readable sentence. Wording may change; the code will not.

429

1300 — the per-organization request rate or concurrent-call limit was reached. Carries Retry-After.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

503

1501 — a service this endpoint depends on is unreachable or returned a 5xx.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

curl -X DELETE "https://api.graine.ai/v2/api-keys/key_1a2b3c4d5e6f7890?organization_id=string" \
  -H "Authorization: Bearer <token>"

The key's new state. Revocation is a deactivation, not an erasure.

{
  "key_id": "key_1a2b3c4d5e6f7890",
  "status": "inactive",
  "revoked": true,
  "revoked_at": "2026-08-27T09:30:00.000Z"
}