Facilitator API

The facilitator is an Express server that handles session creation, x402 verification, and on-chain settlement. The hosted instance lives on Railway:

https://inco-facilitator-production.up.railway.app

It pays the SOL fee for every settle from its own funded keypair — no Kora or external paymaster needed. Source: IncoPay/inco-facilitator.

Base URL

Default in the IncoPay app: https://inco-facilitator-production.up.railway.app. To point at a self-hosted instance, set NEXT_PUBLIC_FACILITATOR_URL in .env.local.

Endpoints

Session-scheme (sign once, settle many)

| Endpoint | Method | Purpose | |----------|--------|---------| | /health | GET | Liveness + facilitator pubkey + token mint | | /supported | GET | Advertise x402 v1+v2 kinds (scheme: session, network: solana:devnet) | | /sessions | POST | Open a new session (the SDK calls this for you) | | /sessions/:id | GET | Inspect session state (cap, spent, expiration) | | /verify | POST | Verify a session payment header | | /settle | POST | Settle a per-call payment against an open session |

Single-payment (one-shot x402)

| Endpoint | Method | Purpose | |----------|--------|---------| | /pay/getAmount | POST | Return ciphertext for a priced amount | | /pay/verify | POST | Verify Ed25519 signature over the payment message | | /pay/settle | POST | Build unsigned tx → (after user signs) submit on-chain |

Session flow

The SDK (solana-x402-sessions) drives this:

  1. Client calls createSession({ ... }) — opens an on-chain approve allowance to the facilitator and POSTs the auth message + signature to /sessions.
  2. The facilitator records the session in sqlite and returns a sessionId.
  3. Subsequent session.fetch(...) calls auto-attach a PAYMENT-SIGNATURE header. The resource server forwards to /settle.
  4. /settle checks the cap, builds an [Ed25519SigVerify, transfer_with_authorization] transaction, signs as fee-payer, submits.

Single-payment flow (/pay/*)

A two-step settle for a one-off payment:

  1. POST /pay/getAmount with { amount, decimals } — returns { ciphertext }.
  2. Client signs an authorization message that binds the ciphertext + recipient.
  3. POST /pay/verify validates the signature.
  4. POST /pay/settle (first call) — returns requiresPayerSignature: true + unsignedTransaction (base64).
  5. User signs the transaction in their wallet.
  6. POST /pay/settle (second call) with the signed transaction — facilitator co-signs as fee-payer and submits.

On success, the response includes success: true and a transaction signature for Solana Explorer.

Self-hosting

Required env for IncoPay/inco-facilitator:

| Variable | Purpose | |----------|---------| | FACILITATOR_KEYPAIR | Inline JSON array [1,2,...] or base64 of the 64-byte secret. The facilitator pubkey signs as fee payer. | | TOKEN_MINT | IncoToken mint pubkey on devnet | | SOLANA_RPC_URL | optional override; defaults to https://api.devnet.solana.com | | PORT / FACILITATOR_PORT | listening port; defaults 4021 |

For request/response shapes, see inco-facilitator/src/routes/ in the repo.