Skip to main content

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:
  1. Request - Request authorization and policy evaluation
  2. Execute - Execute the approved payment onchain
Or use 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.execute() is for managed wallets. If your agent holds the signing keys, use the external-wallet approve -> confirm flow instead.

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 of payments.execute():
  1. Call POST /api/sdk/payments/approve to evaluate policy and receive an approvalToken
  2. Submit the onchain transfer through your own signer or wallet integration
  3. Call POST /api/sdk/payments/{requestId}/confirm with the final txHash, plus the approvalToken when the original /approve response returned one
This keeps the same policy checks and audit trail while leaving execution in the agent’s control. It does not cryptographically block a direct transfer signed outside Conto.
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 with GET /api/sdk/approval-requests?type=payment&status=PENDING and submit the assigned human owner’s explicit decision with:
This route requires 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

Use idempotencyKey when your caller may retry the same payment request because of network timeouts or uncertain client state.
  • Same idempotencyKey + same request payload: returns the original requestId and current next action
  • Same idempotencyKey + different request payload: returns HTTP 409 with code: "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 ContoError with code PAYMENT_DENIED
  • If requires approval: Throws ContoError with code REQUIRES_APPROVAL
  • If an additional action is required: Throws ContoError with code ACTION_REQUIRED and a validated actionUrl

Example

autoExecute Flag

The autoExecute flag lets you request authorization and execute the payment in a single API call, without needing a separate execute() call.
Requires both payments:request and payments:execute scopes. The standard SDK key preset includes both. If a key lacks payments:execute (for example, a legacy custom-scoped key), the flag is silently ignored and the response is a normal APPROVED status that you must execute separately.

How It Works

  • If APPROVED + autoExecute: true: Starts execution and returns status: "PROCESSING"; a customer receipt is included once execution has produced a transaction ID and hash
  • If DENIED or REQUIRES_APPROVAL: autoExecute is ignored, normal response returned
  • If automatic execution does not start: Returns status: "APPROVED" with an actionUrl for 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

Including purpose improves audit trails and analytics:
Approvals from /request expire after 5 minutes. Approvals from /approve (external wallets) expire after 10 minutes. Check expiration before executing:
Use separate request/execute when you need to:
  • Validate before executing
  • Show user confirmation
  • Handle requires_approval status
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