Skip to Content
Simpang Router

Management API

Manage keys, usage, members and budgets from scripts.

Everything you can do on your own pages, plus the workspace owner and admin pages, is also a REST call. The MCP server exposes the same actions as tools.

Tokens

The API uses management tokens, not API keys. Create one in Settings → Management tokens.

  • Tokens start with sk-spm- and are shown once.
  • A token acts as you, with your roles. It can't do anything you can't do in the app.
  • Read tokens can only call GET routes. Read and write tokens can call all of them.
  • Tokens expire after 30, 90 or 365 days, or never. Pick when you create one; a token that never expires lasts until you revoke it.
  • Tokens never work for model calls, and API keys never work here.
  • Tokens can't create other tokens. That only happens in the app.
curl https://simpang.zakiego.com/api/manage/v1/me \
  -H "Authorization: Bearer sk-spm-..."

Responses

Success is 200 with { "data": ... }. Errors look like this:

{ "error": { "code": "read_only_token", "message": "This token is read-only. ..." } }
StatusCodes
400invalid_request, invalid_json, nothing_to_change
401invalid_token (missing, wrong, revoked or expired)
403read_only_token, not_allowed, owners_only, super_admin_only, workspace_suspended
404route_not_found, workspace_not_found, key_not_found, member_not_found, invite_not_found, budget_not_found
409last_owner, no_models
429rate_limited, with a Retry-After header

Each token gets 120 calls a minute. Too many bad tokens from one IP gets that IP a short pause.

Routes

All paths are under /api/manage/v1. GET /api/manage/v1 lists them as JSON. Query params on GET routes take lists as a,b or repeated params.

You

MethodPathScopeDoes
GET/mereadYour account, the token's scope, and your workspaces
GET/workspaces/:workspaceId/keysreadYour keys, masked, with spend and limits
POST/workspaces/:workspaceId/keyswriteNew key. Body: name, expiresInDays, monthlyLimitUsd, modelAllowlist, rpmLimit, concurrencyLimit
PATCH/workspaces/:workspaceId/keys/:keyIdwriteBody: name and/or disabled
DELETE/workspaces/:workspaceId/keys/:keyIdwriteRevoke a key
GET/workspaces/:workspaceId/modelsreadModels you can call, with prices
GET/workspaces/:workspaceId/usagereadOverview. Query: range (24h, 7d, 30d, 90d), scope (me, workspace)
GET/workspaces/:workspaceId/analyticsreadTime series, plus a breakdown by thinking budget. Query: range, scope, keys, models, clients
GET/workspaces/:workspaceId/activityreadYour requests. Query: range, key, model, status, client, stream, thinking, cursor, limit

Workspace owners and admins

scope=workspace on usage and analytics also needs this role.

MethodPathScopeDoes
GET/workspaces/:workspaceIdreadBudgets, models, members and open invites
PATCH/workspaces/:workspaceIdwriteRename. Body: name
GET/workspaces/:workspaceId/members/:memberIdreadOne member with budgets, ledger and keys
PATCH/workspaces/:workspaceId/members/:memberIdwriteBody: role and/or models (null = all models)
DELETE/workspaces/:workspaceId/members/:memberIdwriteRemove a member. Anyone can remove themselves to leave
PUT/workspaces/:workspaceId/members/:memberId/budgets/:periodwriteCap for day, week, month or total. Body: usdLimit (like "25.00"), tokenLimit
POST/workspaces/:workspaceId/grantswriteExtra budget this period. Body: budgetId, usd, reason
GET/workspaces/:workspaceId/invitesreadInvites and their status
POST/workspaces/:workspaceId/inviteswriteBody: email, role, expiresInDays. Returns the link once
DELETE/workspaces/:workspaceId/invites/:inviteIdwriteRevoke an invite
DELETE/workspaces/:workspaceId/member-keys/:keyIdwriteRevoke a member's key

Same rules as the app: only owners touch owners, admins can't lift their own cap, and a workspace keeps at least one owner.

On this page