API overview
AgentValet exposes two public API surfaces:
- The agent API at
https://api.agentvalet.ai/v1/*. Every call is signed by the agent’s RS256 key and brokered to the upstream SaaS platform viaread_platform,write_platformordelete_platform. This is what your agent invokes at runtime. - The owner API at
https://api.agentvalet.ai/v1/approvals/*and via Supabase Edge Functions athttps://<project>.supabase.co/functions/v1/*. These are the dashboard’s writes (approve, revoke, register, audit). Most operators won’t call these directly — they’re documented for enterprise integrators building custom dashboards.
For everything else (billing, OAuth callback, webhooks), there’s no public contract and we reserve the right to change the surface area without notice.
How agents call AgentValet
The recommended path is through the AgentValet MCP server, not by
hitting /v1/actions directly. The MCP server handles JWT signing,
endpoint discovery, error envelope parsing, and the long-poll for
approval results. If you’re building inside Claude Code, Claude Desktop,
Cursor, or another MCP-aware host, install the AgentValet MCP and call:
write_platform({
platform: "slack",
endpoint: "/api/chat.postMessage",
scope: "slack:write",
body: { channel: "#general", text: "Hello" }
})Reads use read_platform (always GET, no method argument) and deletions
use delete_platform (always DELETE). write_platform accepts POST, PUT
or PATCH, defaulting to POST.
The MCP server signs the request, sends it to POST /v1/actions, waits
up to 50 seconds for owner approval if needed, and returns the upstream
SaaS response. See Get started for installation.
Which package do I want?
| You’re building | Use | Why |
|---|---|---|
| An agent inside Claude Code, Claude Desktop, Cursor, or another MCP host | @agentvalet/mcp-server | No code. Install it, call read_platform / write_platform / delete_platform |
| A Node agent that isn’t MCP — LangChain, a cron job, a service | @agentvalet/client | Same governance, a typed SDK instead of raw HTTP |
| A Python agent that isn’t MCP | agentvalet | The Python port. Same endpoints, same approval semantics, sync and async |
| A CrewAI crew | crewai-agentvalet | Builds one typed CrewAI tool per granted platform |
| Your own MCP server, and you want policy enforced inside it | @agentvalet/mcp-broker | Wrap once; every tool is checked, credentialed, audited |
| Anything else | POST /v1/actions | You sign the JWT and handle approvals yourself |
Reach for the raw endpoint last. Calling it directly means implementing RS256
assertion signing, the 202 owner-approval long-poll, and the retry semantics
by hand — all of which the packages above already do.
import { AgentValet } from "@agentvalet/client";
const av = AgentValet.fromEnv();
await av.call({
platform: "slack",
endpoint: "/api/chat.postMessage",
method: "POST",
scope: "chat:write",
data: { channel: "#general", text: "Hello" },
});If you still need the raw endpoint, see POST /v1/actions.
Authentication
All agent-facing endpoints require an RS256-signed JWT in the
Authorization: Bearer <token> header. Claims:
| Claim | Required | Notes |
|---|---|---|
agent_id | yes | The agent’s UUID as shown in the dashboard |
owner_id | yes | The owning organisation’s owner UUID |
iat | yes | Issued-at timestamp (seconds) |
exp | yes | Expiry — recommended ≤ 5 minutes from iat |
sub | optional | If present, must match the agent’s spiffe_id |
The JWT is verified against the public key registered for the agent
(agents.public_key_pem). Mismatches return 401 invalid_signature
and increment the circuit breaker.
The Paperclip company-key path is also supported for the Paperclip adapter — see the in-app guide on Paperclip key setup.
Owner-facing endpoints
Dashboard mutations use the owner’s Clerk JWT in the same
Authorization: Bearer header. The proxy verifies the JWT against
Clerk’s JWKS at https://clerk.agentvalet.ai/.well-known/jwks.json.
Rate limits
| Endpoint group | Limit | Notes |
|---|---|---|
POST /v1/actions | Per-agent, per-minute. See your plan. | Independent of upstream SaaS rate limits |
GET /v1/approvals/:id | 60/min per agent | Polling the result of a pending approval |
GET /v1/agents/me/pending-actions | 30/min per agent | 24h pending + completed window |
POST /v1/approvals/passkeys/* | 10/min per IP | WebAuthn register / sign |
Exceeding a limit returns 429 Too Many Requests with a
Retry-After header.
Error envelope
All errors return a JSON body with this shape:
{
"error": "scope_not_granted",
"detail": "Agent does not have permission for slack:write",
"correlation_id": "01HKZ7...",
"report_hint": {
"url": "https://api.agentvalet.ai/v1/agents/self/diagnostics",
"suggested_payload": { "severity": "error", "code": "scope_not_granted" }
}
}error— a stable machine-readable identifier. Don’t substring; switch on it.detail— human-readable, may change between releases.correlation_id— Pino request id; quote this when filing a bug or emailing support.report_hint— when present, your agent can POST the suggested payload to lodge a self-report tied back to this request. See report_self_diagnostic.
Endpoint reference
POST /v1/actions— proxy a call to a connected platformPOST /v1/agents/children: mint a scope-attenuated child identity for a subagent- Approvals API — owner-facing decide + agent-facing poll
- Passkeys — WebAuthn enrolment + biometric approval
- Agent pending actions — agent introspection