vermilion
guides

Scoped API keys

An API key can be restricted to a set of capability scopes, a rolling spend cap, a request-rate limit, and an expiry. This lets you hand a key to an automated integration — an AP or procurement agent, a background worker — that can do exactly one job and no more, bounded by the platform rather than by trust.

Capability scopes

A key with a non-empty scope list may only call operations it holds the scope for; a request outside its scopes returns 403 insufficient_scope. A key with no scopes has full access (the default, so existing keys are unchanged).

Spend cap

A spend cap bounds how much a key may initiate within a rolling window. Set the amount (in the currency’s minor units), the currency, and the window in seconds. A capped key may only transact in its cap currency, and a payment that would exceed the remaining budget is rejected with 403 spend_cap_exceeded — enforced atomically, so concurrent payments cannot slip past the cap. Cleanly-failed payments don’t consume budget.

Creating a scoped key

Create keys in the dashboard under API keys, or via the dashboard API (owner/admin only). The secret is returned exactly once and stored hashed.

POST /dashboard/v1/api_keys { "name": "procurement-agent", "scopes": ["payments:write", "payments:read"], "spend_cap": { "amount": 500000, "currency": "EUR", "window_seconds": 86400 }, "rate_limit_per_minute": 60, "expires_at": "2026-12-31T00:00:00Z" }

Revoke a key at any time (owner/admin) — the kill switch for a misbehaving integration.

Using a scoped key with an AI agent

Scoped keys are the safe way to let an AI agent transact on your behalf: give the agent a key scoped to payments:write with a daily spend cap, and the platform enforces the ceiling regardless of what the agent tries. The MCP server in apps/mcp exposes the payment API to MCP-capable agents (Claude and others) using exactly such a key; the normalized insufficient_scope and spend_cap_exceeded errors are surfaced to the agent so it can react.