Agents API
The Agents API is split between two surfaces:
- Tenant-admin (dashboard) —
/v1/auth/dashboard/tenants/{slug}/agents/**, session-authenticated, owner-role required for write operations. - End-user —
/v1/users/me/agents, JWT-authenticated, scoped to the caller’s user identity within the resolved tenant.
Cross-tenant access on either surface returns 404, never 403, per project convention.
The canonical machine-readable spec is the API reference. What follows is a human guide; field-level shapes are authoritative in the OpenAPI document.
Tenant-admin surface
Section titled “Tenant-admin surface”Register an agent
Section titled “Register an agent”POST /v1/auth/dashboard/tenants/{slug}/agentsContent-Type: application/json{ "name": "Concierge bot", "description": "Books rooms on behalf of guests", "agent_class": "mcp-server", "scopes": ["read:bookings", "write:bookings"], "grant_types": [ "urn:ietf:params:oauth:grant-type:token-exchange", "urn:openid:params:grant-type:ciba" ], "agent_token_max_ttl_sec": 300, "agent_settings": { "rate_limits": { "api_calls_per_min": 120 }, "max_concurrent_tokens": 50 }}Response 201: { ...AgentResponse, client_secret } — secret revealed
exactly once.
Errors:
400 oauth_client/use_agents_endpoint— sent if you POSTedclient_type: 'agent'to the legacy/oauth-clientsendpoint. Soft-redirect — use the agents endpoint instead.403 agent/tier_unauthorized— Free tier; upgrade to Pro+.422 agent/invalid_grant_type— grant outside the agent allowlist ({token-exchange, ciba, device-code, client-credentials}).422 agent/invalid_field—redirect_urisnon-empty (agents are headless).
List agents
Section titled “List agents”GET /v1/auth/dashboard/tenants/{slug}/agentsGET /v1/auth/dashboard/tenants/{slug}/agents?include_revoked=trueCursor-paginated (default limit=20, max 100). Default selector:
clientType='agent' AND revoked_at IS NULL. Pass include_revoked=true to
see revoked agents.
Get / update / rotate-secret
Section titled “Get / update / rotate-secret”GET /v1/auth/dashboard/tenants/{slug}/agents/{agentId}PATCH /v1/auth/dashboard/tenants/{slug}/agents/{agentId}POST /v1/auth/dashboard/tenants/{slug}/agents/{agentId}/rotate-secretPATCH bumps agent_metadata_version. Rotate-secret reveals the new secret
exactly once.
PATCH and rotate-secret on a revoked agent → 409 agent/already_revoked.
Revoke an agent (immediate, all tokens)
Section titled “Revoke an agent (immediate, all tokens)”DELETE /v1/auth/dashboard/tenants/{slug}/agents/{agentId}Response 200: { id, name, revoked_at, agent_metadata_version }.
Revocation is atomic — every step below either all happens or none of it does:
- The agent is marked revoked (conditional — a second call is a no-op).
- Already-issued tokens for that agent are denylisted for the remainder of their maximum lifetime, so revocation takes effect immediately rather than waiting for tokens to expire.
- An
agent.revokedaudit event (HIGH severity) + webhook fire. - All tenant owners are notified by email.
Revocation is enforced on every request after signature verification, so a
token issued before revocation stops working at once; the rejection is
WWW-Authenticate: Bearer error="invalid_token", error_description="agent_revoked" 401.
Idempotent — re-revoking returns 200 with the existing revoked_at and
fires no second audit / webhook.
Activity timeline
Section titled “Activity timeline”GET /v1/auth/dashboard/tenants/{slug}/agents/{agentId}/activity ?cursor=&limit=50&since=&until=&actor_user_id=&action_type=Returns { data: AgentActionResponse[], pagination: { next_cursor, has_more } }.
Default limit=50, max 200. RBAC: only tenant.role === 'owner' may read
other users’ actions.
AgentActionResponse fields: id, action, actor_user_id?,
actor_user_email?, resource?, method_or_event?, jti?,
scope_used?, ip_hash_prefix? (12 chars), user_agent_hash_prefix?,
created_at. Raw IP / UA hashes are never returned.
End-user surface
Section titled “End-user surface”List agents acting on me
Section titled “List agents acting on me”GET /v1/users/me/agentsAuthorization: Bearer <user-jwt>Returns { data: UserAgentResponse[] }, sorted by last_action_at DESC.
UserAgentResponse fields: agent_client_id, agent_name,
agent_logo_url?, agent_class?, last_action_at?, action_count,
revoked_at? (this user revoked), agent_revoked_at? (tenant admin
revoked).
Revoke (GDPR Art. 7(3))
Section titled “Revoke (GDPR Art. 7(3))”DELETE /v1/users/me/agents/{agentClientId}Authorization: Bearer <user-jwt>Inserts a user_agent_revocations row keyed (tenant_id, user_id, agent_client_id)
with reason='gdpr_art_7_withdrawal'. Token-issuance gates in
token-exchange + CIBA reject any future mint where (act.sub, sub) matches.
Important: already-issued tokens remain valid until their TTL expires
(≤900s ceiling). For instant per-token invalidation across all users, the
tenant admin uses DELETE /v1/auth/dashboard/tenants/{slug}/agents/{agentId}.
Response 200: { agent_client_id, revoked_at, reason }. Idempotent.
Rate limits
Section titled “Rate limits”- Writes and reads/activity are rate-limited independently, at the standard auth-surface limits.
- Per-agent overrides are configurable on the agent’s settings:
token_exchange_per_min,ciba_initiate_per_min,device_code_per_min,client_credentials_per_min,api_calls_per_min. An override is clamped to a platform hard ceiling — a tenant cannot dial an agent above it. - Hits emit
agent.rate_limitedaudit events with the offending scope and the computed limit. A429carriesRetry-After, so back off on that rather than on a hard-coded assumption about the limit.
SDK helpers
Section titled “SDK helpers”The Node SDK exposes the end-user surface only (admin endpoints stay in the dashboard’s session-auth realm):
import { RakomiClient } from '@rakomi/node';
const client = new RakomiClient({ apiKey: process.env.RAKOMI_API_KEY! });const userToken = '<end-user-jwt>';
const list = await client.users.me.agents.list({ userToken });if (list.ok) { for (const agent of list.data.data) { console.log(agent.agent_name, agent.action_count); }}
const revoked = await client.users.me.agents.revoke({ userToken, agentClientId: 'agent_abc',});Both helpers return the SDK’s Result shape ({ ok: true, data } | { ok: false, error })
and never throw on expected 4xx responses. Typed errors are exported for
instanceof checks: AgentsUnauthorizedError, AgentNotFoundError,
AgentsRateLimitedError, AgentsNetworkError.