Graine AI
API referenceClient tokens

Create a client token

Mint a short-lived token for one of your users, from your server, with your secret API key.

Mint a short-lived token for one of your users, from your server, with your secret API key.

Your app's SDK takes it from its tokenProvider and sends it with every request; the SDK asks for a new one shortly before it expires. A token that expires never ends a chat or call in progress — only new conversations need a fresh one. Turn on the agent's Require server tokens (report-only first, then enforce) under Agent → Embed & Widgets → Install → Server tokens; once it is enforced, a request without a valid token for that agent and user is refused, and each route needs the scope that covers it (a token without memory cannot read what the agent remembers). Mint on your server only: the API key must never reach an app or a web page. A deleted agent gets no token (409, code 1203).

Rate limit: 2000 requests per minute per organization, counted together with every endpoint that has no stricter limit of its own. Exceeding it returns 429 with Retry-After; the X-RateLimit-* response headers report your remaining allowance on every call.

POST
/v2/client-tokens
/v2/client-tokens

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

Request Body

application/jsonRequired

agent_id
Required
Agent Id

The agent the token is for, as the dashboard shows it.

user_id
Required
User Id

Your user's identifier in the field the agent's Who is the user? setting names — user_id, email, phone or your own field — exactly what your app passes to identify(). 1 to 256 characters.

scopes
Required
Scopes

What the app may do with the token: chat (open a chat), call (start or answer a voice call), memory (read or clear what the agent remembers about the user), booking (book, list or cancel calls) and workflows (start a workflow). One to five of them.

ttl_secondsTtl Seconds

How long the token lasts, 60 to 3600 seconds.

Default: 3600

Response Body

200

The token for that user and agent.

token
Required
Token

The token. Hand it to your app, which passes it back to the SDK from its tokenProvider. Treat it as a credential for that user: never log it.

expires_at
Required
Expires At

When it stops opening new conversations (ISO 8601, UTC).

expires_in
Required
Expires In

The same, as seconds from now.

agent_id
Required
Agent Id

The agent it is for.

scopes
Required
Scopes

The scopes it carries.

400

1000 — malformed or contradictory input. 1002 — a required parameter is missing.

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.

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.

409

1203 — the agent was deleted, so no token is minted for it.

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 POST "https://api.graine.ai/v2/client-tokens" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agt_0123",
    "user_id": "cust-42",
    "scopes": [
      "chat",
      "call"
    ],
    "ttl_seconds": 900
  }'

The token for that user and agent.

{
  "token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3Mi.c2ln",
  "expires_at": "2026-10-27T10:15:00Z",
  "expires_in": 900,
  "agent_id": "agt_0123",
  "scopes": [
    "chat",
    "call"
  ]
}