Rails
Zero setup

x402

An independent agent — say, a Cowrie-style FX agent holding a Celo wallet — never needs to know AbaPay exists in advance. The whole exchange happens over plain HTTP, challenge and response.

The flow

  1. 1Holds or uses a Celo wallet.
  2. 2Calls AbaPay's quote / pay_bill endpoint directly.
  3. 3Gets 402 Payment Required back, with the exact price and asset.
  4. 4Signs an EIP-3009 transferWithAuthorization with that same wallet — nothing else.
  5. 5Retries the request with the signed authorization attached.
  6. 6AbaPay settles on Celo via Celo's own x402 facilitator and vends the bill.

Never required for this path

AccountAgent HubAPI keyPINWallet-signature link

Try it — live

Edit the bill, hit send — a probe against production with no payment attached returns a 402 challenge naming the live price. Nothing here moves money.

{
  "serviceID": "mtn",
  "serviceCategory": "AIRTIME",
  "network": "MTN",
  "billersCode": "08012345678",
  "nairaAmount": 1000,
  "token": "USDC",
  "blockchain": "CELO",
  "wallet_address": "0xYourAgentWallet"
}

Request & response

POST /api/pay/x402 — no X-PAYMENT header yet
{
  "serviceID": "mtn", "serviceCategory": "AIRTIME",
  "network": "MTN", "billersCode": "08012345678",
  "nairaAmount": 1000, "token": "USDC",
  "blockchain": "CELO", "wallet_address": "0xYourAgentWallet..."
}
← 402 Payment Required (real field names)
{
  "x402Version": 1,
  "error": "Payment required",
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:42220",
    "asset": "0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e",
    "payTo": "0x5df8aE2B963165b735B18Ca86B1ea448d2AA032C",
    "maxTimeoutSeconds": 86400,
    "extra": { "name": "Tether USD", "version": "1", "primaryType": "TransferWithAuthorization" }
  }]
}
POST /api/pay/x402 -H X-PAYMENT: <base64 signed authorization> → 200 OK
{
  "success": true, "status": "SUCCESS",
  "tx_hash": "0x91a3...4f2c", "request_id": "req_...",
  "purchased_code": null, "units": null
}

Both USDC (0xcebA9300…) and USD₮ settle via Celo's own x402 facilitator — each implements EIP-3009. Full field reference: openapi.json. Every way a challenge or settlement can fail, with real error codes: /agents/errors.

Don't hand-roll the signing

abapay-sdk's payBillViaX402() does exactly the three requests and one signature above — pass it a viem account and the bill details, get back the settlement result.

See the SDK →