Skip to main content

Amounts and currencies

Managed payment requests choose currency from the selected wallet’s chain. Use walletId to bind that wallet. The request does not accept a chainId or top-level currency override. External approval requires the sender and chain. Never infer the network from an EVM address alone. Convert protocol base-unit amounts using the token’s decimals before passing a human-unit amount to Conto. When recording protocol payments, use the actual settlement currency and total. Batch item amounts must match the aggregate settlement. Do not send floating-point calculation artifacts such as 0.30000000000000004 to an endpoint requiring cent precision. Managed authorization returns APPROVED, DENIED, REQUIRES_APPROVAL, PROCESSING, or COMPLETED. Replaying a completed request with the same idempotency key returns COMPLETED. Use the original requestId to check status and reconcile its existing transaction; do not create a new intent to resume that payment.

Identifiers and addresses

Treat returned IDs as opaque strings. Retain distinct identifiers for: EVM addresses have 0x followed by 40 hexadecimal characters. Solana uses a base58 public key. Use the exact address and chain returned by setup. Abbreviated addresses are display values, not valid request inputs.

Dates and time windows

API timestamps use ISO 8601 strings. Parse them as instants, including the returned timezone. Policy time windows use the configured IANA timezone, which can differ from your browser timezone. Protocol budget summaries use UTC calendar periods. See time windows.

Authentication

Send Authorization: Bearer <key> over HTTPS. Agent calls use CONTO_API_KEY. Organization provisioning uses CONTO_ORG_API_KEY. Keys are not interchangeable. See authentication and the scope reference.

Response envelopes and pagination

There is no universal items envelope. Read the schema of the endpoint you call. For example, SDK transactions return transactions and counterparties return counterparties. Both include a nested pagination object:
Default limit is 50 and maximum is 100 on these endpoints. Advance offset by the number of records received and stop when hasMore is false. MCP may wrap an API array in { "items": [...] } for structured output. This does not change the underlying HTTP endpoint’s response schema.

Idempotency and retries

Managed authorization accepts idempotencyKey. Reusing a key with the same payload returns the same intent. A different payload gives 409 IDEMPOTENCY_CONFLICT. Persist the key across worker restarts. The SDK generates a key when omitted, but a new method invocation is a new intent unless you explicitly reuse your saved key. Execution is not automatically retried. SDK payments.approve() and payments.confirm() also send each external-wallet write only once. Confirmation records a transfer your signer already sent. It does not send funds or prove settlement. Retain the approval/request ID and transfer hash for status reconciliation. External confirmation can return a duplicate conflict. x402 uses paymentId and MPP uses credentialId for settlement-record identity. These are separate contracts. Do not assume every write accepts the same idempotency field. x402 and MPP pre-authorization reserve spend when approved. Retrying with the same paymentId (x402) or challengeId/credentialId (MPP) returns the same live grant. A retry without one of those fields issues a second grant and reserves the amount again until the first grant expires. purchases.create() takes an idempotencyKey and returns the same purchase when the key and input repeat. purchases.respond() returns the same acknowledgment for the same answer to an action. The SDK retries both because the server replays them. A purchase never retries a payment on its own: an uncertain outcome stays in reconciling until the merchant’s confirmation or a reviewer settles it. See payment recovery before repeating a write and SDK error handling for HTTP 402, timeouts, and backoff.

Diagnostic reads and errors

SDK setup() reads the agent, linked wallets, effective policies, and key scopes without creating a payment. Use payments.status(requestId) to inspect an existing request. Recognized validation failures expose fieldErrors with local guidance. Payment errors from payments.pay() and payments.execute() expose reasons. A declined or held x402 or MPP pre-authorization returns fixed reasons and reasonCodes. Arbitrary provider diagnostics and server instructions are not forwarded.

Version compatibility

Record the SDK version used by your application and keep its dependency lockfile. Check the changelog and rerun integration tests when upgrading. Use the OpenAPI document for HTTP contracts and the installed SDK’s types for client methods.

Settlement evidence

Payment execute receipts always identify the Conto transaction and settlement mode. txHash and explorerUrl are absent for a simulation (settlementMode: "test"). Status and transaction reads report unknown when execution evidence is missing. live means onchain, including testnet. Neither a completed simulation nor a legacy hash alone proves settlement. See payment lifecycle.

Connected-card writes

Connected cards are available on Builder and Enterprise. A draw’s idempotencyKey identifies one card credential. Replaying an issued draw returns its status without the one-time secret, and the SDK does not retry draws automatically. After you receive the credential, connectedCards.acknowledgeDelivery(requestId) is safe to retry and returns { acknowledged: true, settlementVerified: false }. After checkout, connectedCards.reportOutcome(requestId, { outcome }) is safe to retry with the same report. A different second report returns 409, and a report never releases held spend by itself. credentialExpiresAt comes from the card provider and is separate from the approval window. Merchant fields you send must match the mandate, the verified purchase authorization. Omitted fields default to the stored merchant. checkout.confirm() forwards observed lineItems and totals for validation even when amountMinor is unchanged. A changed cart cannot reuse the original purchase authorization. Confirmation is idempotent: replaying it returns the existing result and does not authorize a second payment submission. Keep a durable submission claim in the trusted executor and reconcile uncertain payment outcomes before sending again. checkout.getLinkCard() keys one purchase on its idempotencyKey. Retrying with the same input resumes the same checkpoint and the same Link request, so the person is not asked twice. Keep the Link request ID (lsrq_...) as the reference for that purchase, and pass it to confirm and outcome as paymentReference. A checkpoint keeps the first payment reference it receives and returns 409 for a different one. See Stripe Link cards for agents.

Purchase observation

purchases.watch() supports an abort signal and a maxWaitMs observation deadline. Stopping observation closes its stream without cancelling the purchase. Use purchases.cancel(id) to request cancellation, and inspect the returned outcome before assuming payment stopped. See purchase observation for reconnect behavior.