APIx402Co-sign an x402 payment
Co-sign an x402 payment
Co-sign one x402 payment from a guarded Safe.
- Auth Node Token
- Rate-limited Yes
- Idempotency
Idempotency-Keyequal tobatchId - Guide Co-sign a payment
Co-sign one x402 exact payment from a guarded Safe: an EIP-3009 TransferWithAuthorization, or a Permit2 PermitWitnessTransferFrom through x402ExactPermit2Proxy. A token without an EIP-3009 a Safe can sign (Ethereum USDT, Polygon USDT0) pays through Permit2 only; a SafeTx is refused here. agentSignature is the agent’s signature over the Safe message hash of typedData. Exchain verifies the typed data against intent, checks seller binding and the mandate of the asset intent.asset names, and returns every owner’s signature sorted by owner address, plus a guard receipt for the seller. The authorization window may be at most 600 seconds.
nodeTokenAuthorizationBearer <token>Node Token from the Exchain console. Works for wallets this node registered; the node’s network (preprod or mainnet) decides the network of the request. Use a preprod token in the playground.
Idempotency-Key*stringMust equal batchId, which is the authorization nonce (for a SafeTx, the Safe nonce): 0x and 64 hex characters.
^0x[0-9a-fA-F]{64}$application/json- body
batchId*stringThe authorization nonce as 0x and 64 hex characters (a Permit2 uint256 nonce big-endian). Equal to the Idempotency-Key header.
1 <= length <= 128walletId*WalletId^wal_[0-9A-HJKMNP-TV-Z]{26}$typedData*agentSignature?stringThe agent’s 65-byte signature over the Safe message hash of typedData. Required unless the wallet is a shadow wallet.
^0x[0-9a-f]{130}$intent*context?Allowed. Put signature in the payment payload and receipt at extensions["exchain-guard"].receipt.
application/json- response
decisionId*DecisionId^dec_[0-9A-HJKMNP-TV-Z]{26}$safeMessageHash*Hex32^0x[0-9a-f]{64}$walletAddress*EvmAddress^0x[0-9a-fA-F]{40}$digest*Hex32^0x[0-9a-f]{64}$nonce*Hex32^0x[0-9a-f]{64}$quorumMembers?array<string>signature?stringEvery owner’s 65-byte signature, sorted by owner address, ready for the payment payload.
^0x([0-9a-f]{130})+$receipt?stringGuard receipt: a compact EdDSA JWS by the journal key (kid did:web:<host>#journal, published at /.well-known/did.json) over {v, payer, network, asset, amount, payTo, resourceUrl, nonce, decisionId, journalLeaf, mandateHash, ownerBound, issuedAt}. Attach it to the payment payload at extensions["exchain-guard"].receipt.
shadow?booleanmembers*array<|||||||>1 <= items <= 1boundsRemaining*journalRef*stringasOf*string^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$date-timeschemaVersion*stringWire schema version, "1.1" today.
"1.0""1.1"chainTip*|nullcurl -X POST 'https://cosign.exchain.network/v1/x402/cosign' \ -H 'Idempotency-Key: 0xd830b1c61b024118f4e1dce0c305f81290222d28c2b830accf22c60b0304f946' \ -H 'Content-Type: application/json' \ -d '{ "batchId": "0xd830b1c61b024118f4e1dce0c305f81290222d28c2b830accf22c60b0304f946", "walletId": "wal_01M53M3ZNQQ4DDNPE4262QAZ28", "typedData": { "domain": { "name": "USDC", "version": "2", "chainId": 84532, "verifyingContract": "0x036cbd53842c5426634e7929541ec2318f3dcf7e" }, "types": { "TransferWithAuthorization": [ { "name": "from", "type": "address" }, { "name": "to", "type": "address" }, { "name": "value", "type": "uint256" }, { "name": "validAfter", "type": "uint256" }, { "name": "validBefore", "type": "uint256" }, { "name": "nonce", "type": "bytes32" } ] }, "primaryType": "TransferWithAuthorization", "message": { "from": "0x9f2b6c1e4d7a3058b2e6f1c9d4a7b3e5f0c8a216", "to": "0x6d2f8a4c1e9b3075d8a2f6c4e1b9d3a7f5c0e284", "value": "500000", "validAfter": "0", "validBefore": "1793974027", "nonce": "0xd830b1c61b024118f4e1dce0c305f81290222d28c2b830accf22c60b0304f946" } }, "agentSignature": "0x8a52bb619f12c4eb51b5297ac6bffd2eba6e81ff075e35d917b104352f93eae2b218c2eaa10c4aee2d8e8128de363bda0c853a72f6f1cfd1b7596ea3c862c7e41c", "intent": { "purchaseId": "att_01M53M3ZR1088SNXVGAJ9SFR2T", "counterparty": "eip155:84532:0x6d2f8a4c1e9b3075d8a2f6c4e1b9d3a7f5c0e284", "amount": "500000", "asset": "eip155:84532/erc20:0x036cbd53842c5426634e7929541ec2318f3dcf7e", "agentIdentifier": "research-agent", "resource": "https://api.seller.example/v1/report" }}'{ "decisionId": "dec_01M53M3ZR1088SNXVGAJ9SFR2V", "safeMessageHash": "0x26ebe1acc814c822010eb2abe7e27178aebe0fcf2467a5e58e6b50be46ab7fab", "walletAddress": "0x9f2b6c1e4d7a3058b2e6f1c9d4a7b3e5f0c8a216", "digest": "0x9132f370787dedf90c6d69f0ff12a9f7a8471d58cfb86c0a842d69f4e72bd81f", "nonce": "0xd830b1c61b024118f4e1dce0c305f81290222d28c2b830accf22c60b0304f946", "quorumMembers": [ "exchain-eu-1a", "exchain-eu-1b", "exchain-eu-1c" ], "signature": "0x32d0fed30f3ccd8de52142a203227ea2d59c5f7ff529ab014b9d95023082dcafe190023975d13442ade43fa17a5ee4424a773791a1e4809d83ef786dbf6703491b7ad110a292193bfd59e7a8edb3e3d8fec0963c9c5b49b5e6e5c334bd1a9c803e58aa61dc2b210d7497844e5be671c1fd5a7f57f3545ffdbd8ef5b5b5788dc7f41b55570466ad06c009dd4dff5135a8e5b88cb20680a5e235b4d85c51d91ad1211213556442ee8a489a860e51048aab630d8695ed509393bbf1e49e8be23eae8f811b9d111cda2f3f27e05c6f3d19ea01e5176fe1c214e1f8bf0847577ba989a1ba3bf5ca770272fe92850b3cd7814c9b8be6202943343daf015e095ac3ee734d11fa1b", "receipt": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6Y29zaWduLmV4Y2hhaW4ubmV0d29yayNqb3VybmFsIiwidHlwIjoiZXhjaGFpbi1ndWFyZCtqd3MifQ.eyJ2IjoxLCJwYXllciI6ImVpcDE1NTo4NDUzMjoweDlmMmI2YzFlNGQ3YTMwNThiMmU2ZjFjOWQ0YTdiM2U1ZjBjOGEyMTYiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMyIiwiYXNzZXQiOiIweDAzNmNiZDUzODQyYzU0MjY2MzRlNzkyOTU0MWVjMjMxOGYzZGNmN2UiLCJhbW91bnQiOiI1MDAwMDAiLCJwYXlUbyI6IjB4NmQyZjhhNGMxZTliMzA3NWQ4YTJmNmM0ZTFiOWQzYTdmNWMwZTI4NCIsInJlc291cmNlVXJsIjoiaHR0cHM6Ly9hcGkuc2VsbGVyLmV4YW1wbGUvdjEvcmVwb3J0Iiwibm9uY2UiOiIweGQ4MzBiMWM2MWIwMjQxMThmNGUxZGNlMGMzMDVmODEyOTAyMjJkMjhjMmI4MzBhY2NmMjJjNjBiMDMwNGY5NDYiLCJkZWNpc2lvbklkIjoiZGVjXzAxTTUzTTNaUjEwODhTTlhWR0FKOVNGUjJWIiwiam91cm5hbExlYWYiOiJhNWJhOWE3N2QyZDYwYzRhOWI4ZmMwODQ3OGI4MjM2ZDQ3NjAyOTdkOTlkZWNkMjc4NzQwM2ZkNjdmMDFmYTAwIiwibWFuZGF0ZUhhc2giOiI0NzdmOTgxZjNhMWVkYmRjMWZhN2NiYzQ2Zjc4ZmVlYTNmZWQyYzY5M2IxMTZmYjRkYzZiMGFjZjU3OTRmNTQxIiwib3duZXJCb3VuZCI6dHJ1ZSwiaXNzdWVkQXQiOiIyMDI2LTExLTA1VDE0OjIyOjA4WiJ9.2VM9-XHV4ufm9gaDd89LACbfol_ksUsOdbbNacjDxob_G7r_FhTsXv0QIUzauM80d5ejCvRXPe7aFQ_q6ah_JQ", "members": [ { "purchaseId": "att_01M53M3ZR1088SNXVGAJ9SFR2T", "outputIndex": 0, "verdict": "allowed" } ], "boundsRemaining": { "per_tx_cap": { "limit": "1000000", "used": "500000", "remaining": "500000" }, "velocity_burst": { "limit": "60", "used": "1", "remaining": "59", "windowResetsAt": "2026-11-05T14:23:08Z" }, "daily_outflow": { "limit": "500000000", "used": "12500000", "remaining": "487500000", "windowResetsAt": "2026-11-06T08:41:19Z" }, "per_seller_cap": { "limit": "50000000", "used": "3500000", "remaining": "46500000", "windowResetsAt": "2026-11-06T08:41:19Z", "scope": "eip155:84532:0x6d2f8a4c1e9b3075d8a2f6c4e1b9d3a7f5c0e284" }, "per_agent_cap": { "limit": "250000000", "used": "12500000", "remaining": "237500000", "windowResetsAt": "2026-11-06T08:41:19Z", "scope": "0x3c8e1f7a2b9d4e6c0a5f8b1d7e3c9a2f4b6d8e01" }, "envelope": { "limit": "20000000000", "used": "86500000", "remaining": "19913500000" } }, "journalRef": "https://cosign.exchain.network/v1/decisions/dec_01M53M3ZR1088SNXVGAJ9SFR2V", "asOf": "2026-11-05T14:22:07.318Z", "schemaVersion": "1.1", "chainTip": null}Errors
| Status | Code | Meaning |
|---|---|---|
400 | bad_request | The body fails the schema, intent.amount is outside 1..10^18, or intent.counterparty is malformed. |
400 | idempotency_key_mismatch | The Idempotency-Key header differs from batchId. |
400 | batch_id_mismatch | batchId differs from the authorization nonce (for a SafeTx, the Safe nonce). |
400 | clock_rejected | Exchain’s clock check failed. Contact Exchain. |
401 | unauthorized | The bearer credential is missing, unknown or revoked. |
401 | agent_signature_invalid | agentSignature does not recover to the registered agent over the Safe message hash. |
402 | fee_due | Sign fee.typedData’s Safe message hash with the agent key, send it to POST /v1/x402/fees, then send the payment again. |
404 | not_found | The wallet is not an x402 wallet of this node. |
409 | member_denied | The payment was refused; members[0].denied has the code (mandate caps, counterparty_blocked, or seller binding: payee_unpinned, registry_gate, price_above_published, body_mismatch). |
409 | asset_not_listed | intent.asset is not one of the wallet’s governed assets, or Exchain disabled it on the network. |
409 | body_mismatch | The typed data disagrees with intent or uses a method this route refuses; detail says how (for example payee, amount, window, method, nonce_reused, safe_nonce). Do not retry. |
409 | clock_skew | The authorization window is not open now. |
409 | reservation_conflict | Another payment holds a reservation; retry. |
409 | idempotency_conflict | This nonce was decided before with different content (an Error body, not a refusal). |
413 | payload_too_large | The request body is larger than 64 KiB. |
429 | rate_limited | Over the limit; retry after Retry-After seconds (also in retryAfterSec). |
502 | rpc_failed | The chain could not be read (the Safe’s nonce, for a SafeTx payment or a fee Safe transaction); retry. |
503 | quorum_unavailable | Fewer enclaves reachable than the threshold (Retry-After: 5), or detail: "stopped" when Exchain stopped signing (reachable: 0, no retryAfterSec and no Retry-After header). |
503 | unavailable | detail: "record", the audit record could not be written (Retry-After: 5). |
Every code and what to do about it: Errors and codes.