Graine AI

List API scopes and what this key holds

Return the scope taxonomy and the calling key's effective permissions.

Return the scope taxonomy and the calling key's effective permissions.

Deliberately NOT gated by a scope of its own: a key must always be able to discover why it is being refused, or the first 403 becomes a support ticket.

Read key.grandfathered before anything else. When it is true the key was minted before scopes existed, carries no scopes field, and therefore holds every scope listed here — granted shows them all. That is intentional backwards compatibility, not an over-grant: an absent policy has never restricted anything, and reinterpreting it as "deny" would break every integration built against this API so far. An explicitly empty scopes list is honoured as empty and grants nothing.

keys:write is the one exception in both directions: it is never implied by a grandfathered key, and it must be granted deliberately, because minting and revoking credentials is the action that can extend every other one.

Errors: 401 (invalid key), 403 (wrong organization), 429 (rate limited).

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.

GET
/v2/scopes
/v2/scopes

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

Response Body

200

Every scope this API defines, the endpoints each one gates, and whether the calling key currently holds it.

scopes
Required
Scopes

The full taxonomy, in publication order.

key
Required
Key

What the calling key holds.

note
Required
Note

How absent, empty and explicit scope lists are interpreted.

401

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

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 not for the organisation named in the request.

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.

429

1300 — per-organisation rate limit exceeded. 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.

curl -X GET "https://api.graine.ai/v2/scopes" \
  -H "Authorization: Bearer <token>"

Every scope this API defines, the endpoints each one gates, and whether the calling key currently holds it.

{
  "scopes": [
    {
      "scope": "agents:write",
      "description": "Create, replace, update, clone and archive agents.",
      "granted": true,
      "routes": [
        "DELETE /v2/agents/{agent_id}",
        "PATCH /v2/agents/{agent_id}",
        "POST /v2/agents",
        "POST /v2/agents/{agent_id}/clone",
        "PUT /v2/agents/{agent_id}"
      ]
    }
  ],
  "key": {
    "key_id": "key_1a2b3c4d5e6f7890",
    "organization_id": "organization-live-EXAMPLE",
    "scopes_source": "grandfathered",
    "grandfathered": false,
    "granted": [
      "agents:read",
      "agents:write",
      "calls:read",
      "calls:write"
    ]
  },
  "note": "A key minted before scopes existed carries no scopes field and is treated as holding all of them; an explicitly empty list grants nothing. EVERY endpoint that changes something is in this table. The endpoints with no entry are read-only and need only a valid key: GET /v2/user/me, /v2/usage, /v2/api-keys, /v2/scopes, /v2/phone-numbers, /v2/providers, /v2/inbound-agents, the webhook subscription and delivery reads under /v2/webhooks, the knowledge-base reads under /v2/knowledge-bases, and the A/B experiment reads under /v2/agents/{agent_id}/versions. There is no read scope for webhooks or knowledge bases, which is why their reads are ungated and their writes are not. keys:write is never granted implicitly."
}