SDK
Install the TypeScript SDK, call every Arc0 resource from your own backend, and handle approval-held calls.
@arc0/sdk wraps the REST API in a typed client. Use it from any backend
that needs to create connect links, run actions, or read the audit log without going
through an MCP client.
Install
npm install @arc0/sdkThe client
import { Arc0 } from '@arc0/sdk';
const arc0 = new Arc0({ apiKey: process.env.ARC0_API_KEY });The key decides what the client can do — an API key with Read-only access will fail on anything that writes. See API keys.
Connect links
const link = await arc0.connect.createLink({
user: 'u_8f2',
customer: 'northwind',
app: 'salesforce',
});
// { id: 'rc_...', url: 'https://connect.arc0.ai/c/...', expiresAt: '2026-10-04T12:00:00Z' }Send link.url to the user. See Arc0 Connect.
MCP endpoints
const url = await arc0.mcp.endpoint({ user: 'u_8f2' });
// https://mcp.arc0.ai/u/u_8f2Actions
await arc0.actions.run('gmail.send_email', {
user: 'u_8f2',
input: { to: 'ops@acme.com', subject: 'Refund issued', body: 'Your refund is on its way.' },
});
const actions = await arc0.actions.list({ app: 'salesforce' });
// each entry carries its `scope`: read, write or destructiveProxy
const res = await arc0.proxy.fetch({
user: 'u_8f2',
app: 'stripe',
path: '/v1/charges',
method: 'GET',
});Arc0 injects the user's credentials and still applies policies and audit on every call. See REST API and proxy.
Connections
await arc0.connections.list({ user: 'u_8f2' });
await arc0.connections.get('conn_z663h86fl3z2');
await arc0.connections.refresh('conn_z663h86fl3z2');
await arc0.connections.revoke('conn_z663h86fl3z2');
await arc0.connections.export('conn_z663h86fl3z2');
await arc0.connections.reconnectLink('conn_z663h86fl3z2');.export() needs a key with Full access; see Token export.
Users
await arc0.users.list();
await arc0.users.get('u_8f2');
await arc0.users.delete('u_8f2'); // deletes the user and their tokensAudit log
await arc0.audit.list({ user: 'u_8f2', app: 'stripe', decision: 'blocked' });Approvals
await arc0.approvals.approve('apr_9k2m');
await arc0.approvals.reject('apr_9k2m');Your app can decide on an approval this way, or an approver can use the Approve and Reject buttons in the email Arc0 sends. See Approvals.
Policies
const policy = await arc0.policies.get('pol_acme_support');
await arc0.policies.update('pol_acme_support', {
defaults: { read: 'allow', write: 'ask', destructive: 'deny' },
});For the common case of changing one app's grade rules on the default policy, use the shorthand:
await arc0.policies.set('hubspot', { read: 'allow', write: 'ask', destructive: 'deny' });Both write a new version; see Policies.
Error handling
Every failed call throws an Arc0Error with a code, a message and a retryable flag.
The full list of codes covers policy denials, missing or broken
connections, and upstream failures.
An ask rule doesn't fail outright — it throws with code: 'approval_required' and an
approval object:
import { Arc0Error } from '@arc0/sdk';
try {
await arc0.actions.run('stripe.create_refund', {
user: 'u_8f2',
input: { charge: 'ch_1', amount: 2000 },
});
} catch (err) {
if (err instanceof Arc0Error && err.code === 'approval_required') {
console.log('Waiting on', err.approval.requestedFrom, 'until', err.approval.expiresAt);
return;
}
throw err;
}Once an approver decides, the approval.decided webhook tells you it's
safe to call arc0.actions.run again with the same input — approved calls go through, and
the audit log records them as allowed with the reason Approved by {name}.
Retries
Check retryable before retrying anything. upstream_rate_limited, upstream_timeout and
upstream_unavailable are worth a backoff-and-retry; denied_by_policy and
invalid_api_key never are, no matter how many times you call them. approval_required is
marked retryable, but only after the approval resolves — retrying immediately holds the
call again instead of running it.
TypeScript types
The client is written in TypeScript and ships its own types — Connection,
AuditEvent, Policy, Arc0Error and the rest are all importable:
import type { Connection, AuditEvent } from '@arc0/sdk';