CONTO_API_KEY. Do not use
CONTO_ORG_API_KEY for these /api/sdk/* calls. See Keys and scopes.
Before integrating, connect your agent, link a wallet, and generate an SDK key.
If you are an autonomous agent evaluating Conto without a human account,
try the sandbox first.
SDK examples
These use@conto_finance/sdk. See Install the TypeScript SDK.
One-call payment
Usepayments.pay() with a managed wallet to request approval and execute in one call. It throws if
the payment is denied or needs approval.
Approval-aware payment
Userequest() then execute() when your app handles denied or review-required outcomes before
execution.
Setup check
Callconto.setup() on agent startup to read the agent, its wallets, spending limits, and scopes.
The shared payment helper
Each framework integration wraps the same two calls: request (policy check), then execute. This helper calls the REST API directly with no SDK dependency. Define it once and call it from each framework’s tool handler. It:- Sends the payment to
POST /api/sdk/payments/requestwith an idempotency key, so Conto checks it against your policies. - Stops if the result is not
APPROVEDand returns the status,reasons, andactionUrl.pendingistruewhen the payment waits for approval. - Calls
POST /api/sdk/payments/{requestId}/executeonly for an approved request. - Returns the receipt, transaction hash, and explorer URL.
successistrueonly for acompletedpayment with a transaction ID. - Returns
uncertainorcheckStatuswhen the outcome is unknown. It never retries.
processing result means the payment was submitted and awaits confirmation. A sandbox
completed result has a test receipt and does not prove an onchain transfer. Keep the request ID
and idempotency key with the operation. After a timeout or an uncertain response, check
GET /api/sdk/payments/{requestId} before trying again. If the request response was lost, repeat
only the authorization request with the same input and idempotency key to recover it. Do not
start a new payment. Neither helper retries automatically.
The Python equivalent needs pip install requests:
Framework integrations
Each framework needs only its own tool wiring around the shared helper.OpenAI (Responses API)
Anthropic Claude (tool use)
Python (any framework)
Registermake_payment (defined above) as a tool in your framework of choice (CrewAI, AutoGen,
or a custom loop) and return its dict result to the model as the tool output.
Server handlers
These handlers take payment requests on your own server. They are examples: add your own application authentication and authorization, and configure the recipient allowlist before you expose a payment route.Validate before paying
Do not pass an untrusted request body directly topayments.pay(). Put authentication, local
limits, a recipient allowlist, and a caller-supplied idempotency key in front of the SDK. Both
handlers below use this helper:
parsePaymentrejects the body unless the amount is positive and at mostMAX_PAYMENT_AMOUNT(default 50), the recipient is an EVM address onPAYMENT_RECIPIENT_ALLOWLIST, and the purpose is 1 to 200 characters.submitPaymentasks Conto first. A denial returns 403, a payment waiting for approval returns 202, and any other status that is notAPPROVEDreturns 409.- It executes only an approved request. After a timeout, a dropped connection, or a 408, 409, 429, or 5xx error, it reads the payment status instead of retrying.
mapPaymentErrorturns SDK errors into HTTP codes: 400 for validation errors, 409 for idempotency conflicts and insufficient balance, 503 for rate limits, and 502 for anything else.
PAYMENT_RECIPIENT_ALLOWLIST to comma-separated EVM addresses and MAX_PAYMENT_AMOUNT to your
application-level cap.
Express
Connect the helper to an authenticated and authorized Express route. The middleware must verify a user or service identity, enforce your application’s payment-operator permission, and setres.locals.subject. Replace the sample import with your implementation.
Serverless (AWS Lambda)
Put this function behind an API Gateway JWT authorizer and require your application’s ownpayments:create scope on the route. The handler also checks that scope, rejects requests without
a verified subject, validates and caps the body, requires idempotency, and uses the same recipient
allowlist and error mapping as the Express route.
Register an agent in an existing organization
If an organization owner has already invited your agent, register it with the owner’s registration token instead of creating a sandbox. A GET request lists the required fields:payments:request the agent calls POST /api/sdk/payments/request,
which returns a policy decision. With agents:read it reads its own setup with GET /api/sdk/setup
and GET /api/sdk/agents/me. Setup includes the agent’s wallet balances, limits, and policy rules
even though the key has no wallets:read or policies:read. The key has no payments:execute,
payments:approve, or payments:confirm, and it cannot change policies, create keys, or read other
agents. An organization owner issues keys with more scopes. See Keys and scopes.
Read the agent’s setup with the new key:
externalId is optional but recommended: it makes retries idempotent and gives your system a
durable reconciliation key. The registration response confirms the agent status, granted scopes,
credential expiration, and the SDK endpoints that credential can call. It shows the SDK key only on
the first successful registration. Registering the same externalId again returns the existing
agent and credential reference without revealing the key. A retry never changes the key’s scopes.
A key registered before agents:read was included has only payments:request. For that key,
GET /api/sdk/setup returns 403 with code: "INSUFFICIENT_SCOPE", requiredScope: "agents:read",
actor: "owner", and a nextAction. A registration retry returns the same fields in remediation
and leaves setup out of endpoints. Conto never adds scopes to an existing key. An organization
owner generates a new key for the agent and revokes the old one.
Handle errors
HTTP errors carry acode such as VALIDATION_ERROR, AUTH_FAILED, INSUFFICIENT_SCOPE or
RATE_LIMITED. A 5xx or a timeout leaves the outcome unknown, so look up the request status
before retrying execution or creating another payment. See
error handling for every code.
Policy denials are not HTTP errors. /api/sdk/payments/request returns 200 with
status: "DENIED" and a reasons array of fixed messages. Rule names and limits appear only in the
dashboard.
Next steps
Send a payment
Every payment method and response shape
Track and recover a payment
Check status and recover an uncertain result
Webhooks
Receive approval and payment events
Recipes
Curl snippets for payments, policies, x402, MPP, and monitoring