Payments API
The payments API allows agents to request authorization and execute stablecoin payments.Payment SDK routes enforce explicit API-key scopes. Reading payment status requires
transactions:read; requesting, approving, and executing payments require their corresponding
payments:request, payments:approve, and payments:execute scopes.Overview
The payment flow has two steps:- Request - Request authorization and policy evaluation
- Execute - Execute the approved payment onchain
autoExecute: true to request and execute in a single API call. You can also use the SDK convenience method pay() to do both in one call.
Choose The Right Flow
payments.request()
Request authorization for a payment. This evaluates policies without executing.Parameters
External wallet users: If your agent controls its own wallet keys and uses the
/api/sdk/payments/approve endpoint instead, chainId is a required parameter. See the Agent
Skills guide (OpenClaw and Hermes) for the external-wallet flow.If you include
context.invoice, Conto links the invoice details to the payment for
reconciliation and approval review. Supported invoice fields are vendorId, vendorAddress,
id, hash, sourceUrl, payload, expectedAmount, currency, and dueDate. Delta
verification workflows and payment.executed webhook payloads prefer this typed invoice record
for new requests. For a full setup and live test example, see Delta Verification
Setup and Delta Smoke Test.Delta access is currently enabled by Conto during onboarding. If you want to use this flow,
contact sales@conto.finance.
If an approval workflow matches any non-denied request, Conto opens the approval request
immediately and includes
approvalRequestId in the API response. This includes workflows that
intentionally gate otherwise policy-approved payments. If the payment controls require approval
and no custom workflow matches, Conto still opens an actionable review and returns its
approvalRequestId.External Wallet Approve/Confirm Flow
If your agent holds the signing keys, use the external-wallet flow instead ofpayments.execute():
- Call
POST /api/sdk/payments/approveto evaluate policy and receive anapprovalToken - Submit the onchain transfer through your own signer or wallet integration
- Call
POST /api/sdk/payments/{requestId}/confirmwith the finaltxHash, plus theapprovalTokenwhen the original/approveresponse returned one
Confirmation atomically claims an approved external-wallet payment before creating the transaction
record and updating spend tracking. A repeated confirmation for the same request returns a
conflict instead of creating duplicate ledger effects.
If the
senderAddress has not been seen before, Conto auto-creates an external wallet record for
that address and links it to the agent’s organization. That record still counts toward the
organization’s wallet limit, so approval can fail with WALLET_LIMIT_REACHED when the org is
already at capacity.The external-wallet
approve flow accepts the same optional context.invoice object as
payments.request() and stores the same typed invoice fields on the resulting PaymentRequest.If an approval workflow matches,
/api/sdk/payments/approve returns requiresHumanApproval: true
and includes approvalRequestId in the response instead of issuing an approvalToken. After that
workflow approves the payment, POST /api/sdk/payments/{requestId}/confirm can be called with
just the final txHash. Policy-required reviews use the same response shape even when no custom
workflow matches, so every review remains actionable.Agent-skill approval decisions
OpenClaw can list pending reviews withGET /api/sdk/approval-requests?type=payment&status=PENDING
and submit the assigned human owner’s explicit decision with:
payments:approve. It resolves the agent’s assigned owner and still enforces
that person’s transaction-approval permission plus every workflow eligibility and sequencing rule.
When the decision completes the workflow, Conto automatically sends managed-wallet payments and
returns receiptUrl. External wallets receive a nextAction payload containing the exact transfer
and tokenless confirmation handoff.
Response
approvalRequestId is the stable review reference. Use statusUrl to reconcile the request and
follow actionUrl for the next available step. When present, custodyMode tells the caller whether
Conto can execute the selected wallet or the customer’s signer must complete the transfer.
reasons contains customer-facing explanations; provider diagnostics and stored policy records are
not returned.
Payment responses include
currency (for example, USDC, USDT, USDC.e, or pathUSD) so the
caller can reconcile the requested amount with the selected wallet network.Currency depends on chain: The
currency field reflects the stablecoin used on the wallet’s
blockchain. On Base, Ethereum, Arbitrum, and Polygon, both USDC and USDT are supported. On
Tempo Testnet, it is pathUSD. On Tempo Mainnet, it is USDC.e. The amount is always denominated
in the stablecoin configured for the payment.Idempotent Retries
UseidempotencyKey when your caller may retry the same payment request because of network timeouts or uncertain client state.
- Same
idempotencyKey+ same request payload: returns the originalrequestIdand current next action - Same
idempotencyKey+ different request payload: returns HTTP409withcode: "IDEMPOTENCY_CONFLICT" - Different
idempotencyKey: creates a new payment request
Example
payments.execute()
Execute an approved payment request.payments.execute() rechecks ownership and active spending limits before submitting the payment.
Successful responses include the stable Conto transaction ID needed for reconciliation.Parameters
Response
A
processing response means the payment was submitted and should be checked with
payments.status(requestId). Every successful execution includes a stable Conto transaction ID.
Check settlementMode before treating the hash or explorer link as evidence of live settlement.Example
payments.pay()
Convenience method that requests and executes in one call.Behavior
- If approved: Executes immediately and returns result
- If denied: Throws
ContoErrorwith codePAYMENT_DENIED - If requires approval: Throws
ContoErrorwith codeREQUIRES_APPROVAL - If an additional action is required: Throws
ContoErrorwith codeACTION_REQUIREDand a validatedactionUrl
Example
autoExecute Flag
TheautoExecute flag lets you request authorization and execute the payment in a single API call, without needing a separate execute() call.
How It Works
- If APPROVED +
autoExecute: true: Starts execution and returnsstatus: "PROCESSING"; a customer receipt is included once execution has produced a transaction ID and hash - If DENIED or REQUIRES_APPROVAL:
autoExecuteis ignored, normal response returned - If automatic execution does not start: Returns
status: "APPROVED"with anactionUrlfor manual retry
Example
payments.status()
Check the status of a payment request.Response
Example: Polling for Confirmation
Status Reference
The status endpoint returns this compact status set:
When a transaction is present, its status is one of
processing, completed, or failed.
Categories
Use standard categories for better analytics:Urgency Levels
Best Practices
Always Include Purpose
Always Include Purpose
Including purpose improves audit trails and analytics:
Handle Expiration
Handle Expiration
Approvals from
/request expire after 5 minutes. Approvals from /approve (external wallets) expire after 10 minutes. Check expiration before executing:Use Two-Step for Complex Flows
Use Two-Step for Complex Flows
Use separate request/execute when you need to:
- Validate before executing
- Show user confirmation
- Handle requires_approval status
Attach Invoice Details
Attach Invoice Details
Use the typed
context.invoice object when a payment is linked to an invoice:Next Steps
Error Handling
Handle payment errors gracefully
Examples
See complete integration examples