For the complete documentation index, see llms.txt. This page is also available as Markdown.

Using x402 on Keeta

x402 is an open, HTTP-native payments standard built around the 402 Payment Required status code. It lets any HTTP endpoint charge for access — per request, per token, per API call — without accounts, API keys, or subscription billing. A server responds 402 with machine-readable payment instructions, the client signs a payment and retries the request, and the server serves the resource once payment is confirmed.

This guide shows how to accept and make x402 payments on Keeta: as a client paying for a protected resource, as a server charging for one, and how the Keeta x402 facilitator verifies and settles those payments.

x402 on Keeta is implemented by the exact payment scheme, defined in the x402 Keeta scheme specification and shipped as the reference @x402/keeta package. The examples below follow the Keeta x402 example app developed by a community member.

How x402 works on Keeta

Keeta's payment flow follows the general x402 pattern, with one Keeta-specific detail: instead of publishing a transaction itself, the client only signs a block and hands it to the resource server. The facilitator publishes it with a fee block it creates and signs itself as a single vote staple, so that the network fees are covered by the facilitator free of charge.

You can try it out yourself using the interactive demo on the third-party Keeta x402 facilitator.

Review the third-party service notice before using it.

1

Client requests a resource

A client makes a normal HTTP request to a paid endpoint. No payment is attached yet.

2

Server responds with 402

The resource server replies 402 Payment Required with PaymentRequirements: scheme (exact), network, asset, amount, and payTo:

{
  "x402Version": 2,
  "error": "Payment required",
  "resource": {
    "url": "https://facilitator.x402.keeta.com/weather",
    "description": "Get current weather data (demo endpoint)",
    "mimeType": "application/json"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "keeta:1413829460",
      "amount": "1000000",
      "asset": "keeta_anyiff4v34alvumupagmdyosydeq24lc4def5mrpmmyhx3j6vj2uucckeqn52",
      "payTo": "keeta_aab7jq4fx7fl24qk36qpowlyasu3jekv4gdadrz6lhnda3n2upnj2dga7rxjf5a",
      "maxTimeoutSeconds": 300,
      "extra": {}
    },
    {
      "scheme": "exact",
      "network": "keeta:1413829460",
      "amount": "1000",
      "asset": "keeta_apna75yhhvnv4ei7ape55hndk4yepno7a7i2mhtiwahiygixjcnmvswxhnmnk",
      "payTo": "keeta_aab7jq4fx7fl24qk36qpowlyasu3jekv4gdadrz6lhnda3n2upnj2dga7rxjf5a",
      "maxTimeoutSeconds": 300,
      "extra": {}
    }
  ]
}
3

Client signs a block (but doesn't publish it)

The client builds a Keeta block containing a single SEND operation that satisfies the server's requirements, signs it with its Keeta account, and serializes it (ASN.1 DER, Base64-encoded) into the PaymentPayload. It retries the request with a PAYMENT-SIGNATURE header carrying that payload.

{
  "x402Version": 2,
  "payload": {
    "block": "MIH8AgEAAgRURVNUBQAYEzIwMjYwNzAyMTIwMTQwLjY5OVoEIgADAm6dCFFcNSQH4W8GXVEtN6TOPnKi0E8H989NDaWNL2kFAAQgJgvfwf+ZA9wHkB1phDyzxBjbk4PvTHbbtFrAfOEKqN4wUKBOMEwEIgAD9MOFv8q9cgrfoPdZeASptJFV4YYBxz5Z2jBtuqPanQwCAw9CQAQhA3CCl5XfALrRlHgMweHSwMkNcWLgyF6yL2Mwe+0+qnVKBEAGXojraVbFTUlN001p6XXlHpGeEtTsJGuPbCGWgoMLzksWivjcoyk0ZT/kaPFQICd8wa/m9jQIucYCR3B2xvZz"
  },
  "resource": {
    "url": "https://facilitator.x402.keeta.com/weather",
    "description": "Get current weather data (demo endpoint)",
    "mimeType": "application/json"
  },
  "accepted": {
    "scheme": "exact",
    "network": "keeta:1413829460",
    "amount": "1000000",
    "asset": "keeta_anyiff4v34alvumupagmdyosydeq24lc4def5mrpmmyhx3j6vj2uucckeqn52",
    "payTo": "keeta_aab7jq4fx7fl24qk36qpowlyasu3jekv4gdadrz6lhnda3n2upnj2dga7rxjf5a",
    "maxTimeoutSeconds": 300,
    "extra": {}
  }
}
4

Server verifies via the facilitator

The resource server forwards the payload to the facilitator's POST /verify, which decodes the block and checks the signature, the operation, the amount/asset/recipient, and that the signer is authorized to send on behalf of the paying account.

5

Facilitator settles and sponsors the fee

On POST /settle, the facilitator creates and signs its own fee block, collects votes from the network's representatives, and publishes the client's block together with the fee block as a single vote staple, sponsoring the fee itself. It returns a SettlementResponse with the transaction hash to the resource server.

{
  "success": true,
  "payer": "keeta_aabqe3u5bbivynjea7qw6bs5kewtpjgohzzkfucpa7346tinuwgs62mfdqpmlsy",
  "transaction": "E247FE98A3925CB6D5D7CB8C66CE6BDE0C69646326EC3C0F60919C29528C6E99",
  "network": "keeta:1413829460"
}
6

Server returns the resource

The resource server returns 200 OK with the requested content and a settlement receipt header.

{
  "report": {
    "weather": "sunny",
    "temperature": 70
  }
}

Prerequisites

  • A Keeta account for the paying client, and a Keeta account to receive payments on the server side

  • Node.js, with the KeetaNet client SDK and the x402 packages for Keeta:

npm install @keetanetwork/keetanet-client @x402/core @x402/keeta @x402/fetch @x402/express
  • For testnet development, fund your client account from the testnet faucet

Using x402 as a client

This is the "buyer" side, so an app or agent that pays to access someone else's endpoint. The example below uses fetch for payments but you can use any client the x402 reference implementation supports like axios.

See the full example here.

wrapFetchWithPayment does the whole round trip: it sends the initial request, reads the 402, signs a block with clientKeetaSigner, and retries with the PAYMENT-SIGNATURE header attached. x402HTTPClient.processResponse then gives you the payment status.

Using x402 as a server

This is the "seller" side, so charging for an API route. The example below uses Express.js for the HTTP server but you can use any NodeJS framework the x402 reference implementation supports like Next.js, Hono, or Fastify.

See the full example here.

A request without payment gets a 402 back with the PaymentRequirements above; a request from a properly configured x402 client gets a 200 with the JSON payload and a settlement receipt header.

Fee sponsoring on the Keeta facilitator

Every settlement on Keeta's exact scheme is fee-sponsored by the facilitator. The client signs only a payment block for the exact amount owed but it never needs to build or fund a separate fee transaction.

The facilitator cannot redirect funds: it can only append its own fee block alongside the block the client already signed, so it never gains the ability to alter where the client's payment goes.

Facilitators

The following facilitators are known to be available for use.

Third-Party Service Notice

Further reading

Last updated