REST API and proxy

Run actions and call the authenticated proxy over plain HTTP, from any language, with cURL examples.

The REST API is what the SDK and Arc0 MCP both call underneath. Use it directly if you're not in TypeScript, or if you want to see the request on the wire.

Every request needs your API key as a bearer token:

curl https://api.arc0.ai/v1/actions \
  -H "Authorization: Bearer $ARC0_API_KEY"

The base URL is https://api.arc0.ai for every endpoint. See API keys for how access levels and environments work, and the API reference for the full endpoint list.

Running an action

Actions are named app.action, for example gmail.send_email or stripe.create_refund. Run one with:

curl -X POST https://api.arc0.ai/v1/actions/gmail.send_email/run \
  -H "Authorization: Bearer $ARC0_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user": "u_8f2",
    "input": { "to": "ops@acme.com", "subject": "Refund issued", "body": "..." }
  }'

user is the external id of whoever the action runs as — Arc0 looks up their connection to gmail, checks the policy that governs the agent making the call, and either runs it, holds it for approval, or returns an error. A successful call returns:

{ "ok": true, "data": { "id": "18abf2..." } }

Anything else — a policy denial, a held approval, a broken connection, an upstream failure — comes back as an error envelope instead. See Errors.

The authenticated proxy

The proxy lets your backend call an app's own API directly, with Arc0 injecting the user's credentials and still applying policies and audit on every call. It's the REST equivalent of a raw fetch to the provider, minus the credential handling.

curl https://api.arc0.ai/v1/proxy/stripe/v1/charges \
  -H "Authorization: Bearer $ARC0_API_KEY" \
  -H "Arc0-User: u_8f2"

The path after /v1/proxy/{app}/ is passed straight through to the provider, so /v1/proxy/stripe/v1/charges reaches Stripe's /v1/charges. The Arc0-User header tells Arc0 whose connection to use.

Scope grading

The proxy doesn't know your app's action catalog the way /v1/actions does, so it grades each call by HTTP method instead:

MethodScope
GETread
POST, PUT, PATCHwrite
DELETEdestructive

A policy that denies stripe:destructive blocks a DELETE through the proxy exactly as it would block stripe.delete_customer through /v1/actions. Writing to the proxy with a GET isn't possible — the grade follows the method, not the path.

curl -X DELETE https://api.arc0.ai/v1/proxy/salesforce/v1/sobjects/Contact/003... \
  -H "Authorization: Bearer $ARC0_API_KEY" \
  -H "Arc0-User: u_8f2"

If the policy governing this agent holds destructive calls for approval, this returns approval_required instead of reaching Salesforce.

When to use which

Use /v1/actions/{action}/run when the app is enabled in your project and you want Arc0's scope grading, action-level rules and the friendlier app.action naming. Use the proxy when you need an endpoint Arc0 hasn't modeled as an action yet, or when you're porting code that already calls the provider's API directly and needs credentials and governance added.

On this page