x402 on Gonka
checking…

Git: gonkalabs Git is temporarily unavailable. Download the source from this website — Source.

Sellers

Price an HTTP route in GNK or USDC. You return 402, the client pays, you settle through this facilitator, then you serve the work. You do not run a Gonka node.

Server loop

  1. If PAYMENT-SIGNATURE is missing or not valid base64 JSON, respond 402 with PAYMENT-REQUIRED (header and body).
  2. POST /settle with paymentPayload (what the client sent) and paymentRequirements (what you advertised).
  3. If success is false, respond 402 again and put the reason in error.
  4. If success is true, do the work, then return 200 with PAYMENT-RESPONSE set to the base64 settle result.

Gonka uses the upfront payment flow. Do not serve the resource after a verify-only check. /verify is optional and read-only. /settle is what moves funds.

Your 402 body is an x402 v2 PaymentRequired object. Minimum useful accepts entry:

{
  "scheme": "exact",
  "network": "cosmos:gonka-mainnet",
  "amount": "1000000",
  "asset": "ngonka",
  "payTo": "gonka1yourmerchantaddress…",
  "maxTimeoutSeconds": 60,
  "extra": {
    "name": "GNK",
    "decimals": 9,
    "assetTransferMethod": "signed-tx",
    "paymentFlow": "upfront"
  }
}

Add a second object for USDC: set asset to the CW-20 address, decimals to 6, name to USDC. Encode the whole PaymentRequired object as standard base64 for the header. Field list is on Protocol.

Settle before serving

curl -sS -X POST {{BASE}}/settle \
  -H 'Content-Type: application/json' \
  -d '{
    "x402Version": 2,
    "paymentPayload": { "...from PAYMENT-SIGNATURE..." },
    "paymentRequirements": { "...your accepts entry..." }
  }'

On success you get transaction (hex hash), payer, network, and amount. Credit your own ledger if you need one; the chain transfer is already to payTo.

The facilitator rejects a reused TxRaw (replayed_payment). Still enforce that in your app if you run more than one replica and the client retries.

Middleware sketch

async function requirePayment(req, res, next) {
  const header = req.get("PAYMENT-SIGNATURE");
  const required = paymentRequiredFor(req);
  if (!header) return send402(res, required);
  const paymentPayload = JSON.parse(Buffer.from(header, "base64").toString());
  const settled = await fetch(FACILITATOR + "/settle", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      x402Version: 2,
      paymentPayload,
      paymentRequirements: paymentPayload.accepted,
    }),
  }).then((r) => r.json());
  res.set("PAYMENT-RESPONSE", Buffer.from(JSON.stringify(settled)).toString("base64"));
  if (!settled.success) return send402(res, { ...required, error: settled.errorReason });
  next();
}

Pricing

GNK1 GNK = 1000000000 ngonka. Example: 0.001 GNK → amount: "1000000".
USDC1 USDC = 1000000. Example: $0.01 → amount: "10000".
Who receivesYour payTo address. The facilitator never sweeps or holds the payment.

The demo route on this host uses tiny amounts so you can test. Your production amounts are your own.

Discovery

Optional: publish paid URLs so agents can find them. This facilitator exposes GET /discovery/resources for its own /demo. The live catalog is below and on Resource listing. You can run a similar list on your API, or register in an x402 Bazaar later. Shape is in HTTP API.