Raw HTTP / 402 flow
Use the API without an x402 SDK — for custom clients and other languages.
x402 is plain HTTP. You can implement the payment handshake in any language.
The handshake
POST /v1/numbers (no payment)
← 402, PAYMENT-REQUIRED: <base64> (payment requirements)
... decode, sign a Permit2 authorization for `accepts[0]` ...
POST /v1/numbers
PAYMENT-SIGNATURE: <base64> (payment payload)
← 200 { id, number, accessToken }1. Decode the requirements
The PAYMENT-REQUIRED header is base64 JSON:
{
"x402Version": 2,
"resource": { "url": "https://api.sms-x402.xyz/v1/numbers" },
"accepts": [
{
"scheme": "upto",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "1941139",
"payTo": "0xeC73B5405F8511AD20EBE1E4de223DA1e49727ab",
"maxTimeoutSeconds": 1800,
"extra": {
"assetTransferMethod": "permit2",
"facilitatorAddress": "0xB2Bd...371B",
"name": "USD Coin",
"version": "2"
}
}
],
"extensions": { "bazaar": { "info": { "input": ..., "output": ... } } }
}asset— USDC on Baseamount— maximum authorization in atomic units (6 decimals)payTo— where the money goes on settlementextra.facilitatorAddress— the Permit2 spender you authorize
2. Sign the payment (upto / Permit2)
For upto, the payload is an EIP-712 Permit2 PermitTransferFrom signature
authorizing facilitatorAddress to pull up to amount USDC from your address,
with a signature deadline no later than maxTimeoutSeconds from now. The
reference implementation is
@x402/evm upto/client — port it or
wrap it.
3. Send the payload
Base64-encode and retry:
{
"x402Version": 2,
"accepted": { "...": "the requirements you accepted (echo them back)" },
"payload": { "signature": "0x...", "permit2Authorization": { "..." : "..." } }
}Header: PAYMENT-SIGNATURE: <base64 of the above>.
4. Settlement receipt
When your poll delivers the code, the response carries
PAYMENT-RESPONSE: <base64 SettleResponse> — the on-chain receipt (tx hash,
settled amount, payer). If no SMS ever arrives you will simply never see this
header, and no transaction ever touches your wallet.
Error responses
| Status | Meaning |
|---|---|
| 402 | Payment required (first call) or verification failed |
| 400 | Invalid body, or accepted requirements mismatch (scheme/network/asset/payTo/amount) |
| 409 | No numbers available right now |
| 502 | Temporary service or payment-network error — safe to retry |