Skip to main content

Build with x402

Covenant gives builders two things over x402:

  • A free, public facilitator. If you sell anything over HTTP, such as an API, game data or a service an agent calls, the facilitator checks and settles USDC payments for you on Solana and Base. You need no account and no API key, and Covenant pays the network fees from its own wallets.
  • Covenant Compute. AI inference that agents pay for per request in USDC. An agent with its own wallet can buy an answer without an account or API key, and every answer comes with a receipt signed by the operator that ran it. The operator is the server that runs your request; today Covenant runs every operator itself.

Here is how x402 works: a client calls your endpoint, gets HTTP 402 with the price and where to pay, signs a payment, and calls again with that payment in a header. Your server asks a facilitator to verify and settle the payment, then answers. Any x402 v2 client can pay, including agent wallets. Payments settle in USDC on Solana or Base, so a product whose own economy runs on a different chain can still accept them.

Accept payments through the Covenant facilitator

WhatValue
Facilitatorhttps://facilitator.opencovenant.org
Supported paymentshttps://facilitator.opencovenant.org/supported
Solana mainnetsolana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp, USDC EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Base mainneteip155:8453, USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Schemeexact: the buyer pays the price you set
Sourcegithub.com/open-covenant/covenant/tree/main/services/x402-facilitator

It runs on mainnet only; there is no test network.

Set up a seller

With Node 24 and Express, install the official x402 packages, then point the middleware at the facilitator. We ran this setup against the live facilitator, and it returns a 402 that offers payment on both networks.

npm install express @x402/express @x402/core @x402/svm @x402/evm @x402/extensions
import express from 'express';
import { paymentMiddleware, x402ResourceServer } from '@x402/express';
import { HTTPFacilitatorClient } from '@x402/core/server';
import { ExactSvmScheme } from '@x402/svm/exact/server';
import { ExactEvmScheme } from '@x402/evm/exact/server';
import { declareDiscoveryExtension, bazaarResourceServerExtension } from '@x402/extensions/bazaar';

const app = express();
app.use(express.json());

const facilitator = new HTTPFacilitatorClient({ url: 'https://facilitator.opencovenant.org' });
const server = new x402ResourceServer(facilitator)
  .register('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', new ExactSvmScheme())
  .register('eip155:8453', new ExactEvmScheme())
  .registerExtension(bazaarResourceServerExtension);

app.use(paymentMiddleware({
  'POST /api/intel': {
    accepts: [
      { scheme: 'exact', price: '$0.01', network: 'eip155:8453', payTo: '0xYourBaseAddress' },
      { scheme: 'exact', price: '$0.01', network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', payTo: 'YourSolanaAddress' },
    ],
    description: 'Street intel for one district',
    // Optional: lets the facilitator's catalog list this endpoint for agents.
    extensions: {
      ...declareDiscoveryExtension({
        bodyType: 'json',
        input: { district: 'Lowline' },
        inputSchema: { properties: { district: { type: 'string' } }, required: ['district'] },
        output: { example: { district: 'Lowline', heat: 3 } },
      }),
    },
  },
}, server));

app.post('/api/intel', (req, res) => res.json({ district: req.body.district, heat: 3 }));
app.listen(3000);
  • The Solana fee payer is filled in automatically from /supported; you never handle it. On Base, the facilitator submits the buyer's signed USDC transfer and pays the gas.
  • payTo is your own receiving address. On Solana it needs a USDC token account before the first payment.
  • The same works in other frameworks: the x402 project publishes @x402/hono and @x402/next, and HTTPFacilitatorClient with the URL above works in any of them.
  • If the facilitator cannot be reached, the middleware answers 502; if a settlement fails, it answers 402. In both cases your route's response is not sent, so nothing is served without payment.

Get listed so agents can find you

If your route declares the Bazaar discovery extension (the declareDiscoveryExtension block above), the facilitator adds your endpoint to Covenant's public catalog after its first settled payment:

https://facilitator.opencovenant.org/discovery/resources
https://facilitator.opencovenant.org/discovery/search?query=your+words

Each listing is tied to your URL together with your receiving address, so another seller cannot overwrite it. A later paid request with an updated declaration updates your listing; to remove one, write to partnerships@opencovenant.org.

The Bazaar extension is a shared x402 format. Declaring it lists you in Covenant's catalog, not in Coinbase's x402 Bazaar. Coinbase's catalog lists only endpoints that its own facilitator settles, so getting listed there is a separate setup.

Limits

These keep a free service from being abused:

  • USDC only, exact scheme only, and nothing under $0.001.
  • A payment to the payer's own address is refused, so test from a different wallet than your payTo address.
  • Each receiving address can settle up to 500 payments per network per UTC day. Across all sellers, the facilitator settles at most 2,000 payments per network per UTC day. When a cap is reached, the facilitator returns the error pay_to_daily_limit_reached or facilitator_daily_limit_reached, your middleware refuses the request, and the buyer is not charged. The counts reset at midnight UTC. The facilitator does not publish how much of the shared daily cap is left.
  • On Solana, a payment may ask for at most 100,000 compute units at a priority fee of at most 0.1 lamports per unit; standard x402 clients stay well under both. Payments from the Phantom wallet, which adds its own safety checks, may spend at most 20,000 lamports in priority fees. On Base, a smart wallet must already be deployed before it can pay.
  • Your server can make up to 120 verify and settle calls per minute from one IP address. A payment uses one of each, so that is about 60 paid requests a minute per server.

If you expect more volume, write to partnerships@opencovenant.org before you launch. Test with small real payments; the minimum is $0.001, and any x402 v2 client can act as the test buyer, including the one below.

Give your agents paid AI inference

WhatValue
EndpointPOST https://compute-inference.opencovenant.org/v1/chat/completions
Models and prices (free)GET https://compute-inference.opencovenant.org/v1/models
Discovery/.well-known/x402.json and /openapi.json on the same host
Pay withUSDC on Solana or Base; no API key, account or SDK required
Listed onCoinbase's x402 Bazaar and x402scan
  • Model: claude-haiku-4.5, text only. No streaming, tools or images.
  • Input: 1 to 32 messages with the roles system, user or assistant. The messages array, as compact JSON, may be at most 4,096 bytes.
  • Output: up to 2,048 tokens per request.
  • Covenant's operator sends your messages to the model through a third-party model provider, and Covenant keeps the model's response and a hash of your request as the record behind your receipt. Send only what you would send to a hosted model API.

Price

You pay a fixed price before the request runs. It depends on the max_tokens you ask for, not on how many tokens the answer actually uses. Send "pricing": "model_tariff_v1" and the price is $0.012 plus $0.000009 per token of max_tokens:

max_tokensPrice
256$0.014304
512$0.016608
2,048$0.030432

Requests without pricing cost a flat $0.05, which is more than the tariff costs at any max_tokens, so always send it. Current prices, and how long each price stays valid, are at GET /v1/models.

How a paid request works

{
  "model": "claude-haiku-4.5",
  "messages": [{ "role": "user", "content": "Pick tonight's job for a crew of three." }],
  "max_tokens": 512,
  "temperature": 0.2,
  "pricing": "model_tariff_v1"
}
  1. Your first POST returns 402. The body, and the Payment-Required header, offer two ways to pay the same price: USDC on Solana or on Base.
  2. Your x402 client signs one payment and sends the identical body again with the Payment-Signature header.
  3. The model runs. Only once the answer exists is your payment settled, so a failed run is never charged: the payment is simply never submitted.
  4. The answer arrives as an OpenAI-style chat completion, usually 5 to 10 seconds after payment in our tests. The Payment-Response header carries the settled transaction.
  5. Covenant's gateway, the service that takes your payment, holds a paid request for up to 25 seconds while the payment settles. If it needs longer, you get 202 with a Retry-After header: wait, then send the identical request again with the same Payment-Signature. You are not charged twice. The Covenant SDKs do this for you; with a plain x402 client, keep the Payment-Signature you sent so you can repeat it.
  6. Optional: add an Idempotency-Key header containing a UUID. If you resend the same body with the same key before paying, you get the same 402 offer back, so a retry keeps the original price and payment details.
  7. Covenant does not limit requests per wallet. When the service is at capacity it answers 503; retry with backoff.

Pay from an agent

With the official x402 client, paying on Base from Node:

npm install @x402/fetch @x402/evm viem
import { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { privateKeyToAccount } from 'viem/accounts';

const client = new x402Client();
registerExactEvmScheme(client, {
  signer: privateKeyToAccount(process.env.AGENT_PRIVATE_KEY),
  // A spending rule: never pay more than $0.04 for one answer.
  policies: [(version, offers) => offers.filter(offer => BigInt(offer.amount) <= 40_000n)],
});
const pay = wrapFetchWithPayment(fetch, client);

const response = await pay('https://compute-inference.opencovenant.org/v1/chat/completions', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({
    model: 'claude-haiku-4.5',
    messages: [{ role: 'user', content: "Pick tonight's job for a crew of three." }],
    max_tokens: 512,
    pricing: 'model_tariff_v1',
  }),
});
const answer = await response.json();
console.log(answer.choices[0].message.content);

For Solana, use @x402/svm instead: registerExactSvmScheme(client, { signer }) with a signer from @solana/kit (createKeyPairSignerFromBytes). The agent's wallet needs only USDC. It needs no SOL on Solana and no ETH on Base, because the network fees are paid for it.

Check a receipt

Every answer includes a covenant object. Its main fields are envelope (Covenant's signed record of your paid request, called the job), output and output_json (the model's output), and receipt (the operator's signed receipt), along with job_id, quote_id and request_sha256. The receipt lists the status, job hash, result hash, price and time.

The receipt is the operator's signed statement that it produced this output for this job. You can check it later to confirm what you paid for and that the output has not been changed. To check one in any language:

  1. The job is signed with Ed25519 by the gateway key over the text covenant.compute.job.v1 and a newline, followed by envelope.payload_json.
  2. The receipt is signed with Ed25519 by the operator key over covenant.compute.receipt.v1 and a newline, followed by receipt.receipt_json. Signatures and keys are base58 (signature_b58, signer_pubkey_b58).
  3. receipt.job_hash_hex is the SHA-256 of envelope.payload_json, and receipt.result_hash_hex is the SHA-256 of output_json.
  4. Pin the signing keys below rather than trusting the ones inside a response.
KeyValue
Operator9fefASd52qfR2Q8P81yXtkHu9E4q9KvW58x2ixBAAvLR
GatewayF9KjruGNU9f9tr5RXiBZfENeD6f8qAMUX5LQDEt9qdn1

When a key changes, the new key is listed here with the date it took effect, and the previous key stays listed so earlier receipts can still be checked. For a complete reference implementation, see proof.mjs in the JavaScript SDK.

Covenant SDKs

The SDKs are optional. They add receipt checks, spending caps and a local record of purchases, so an agent that crashes and restarts never pays twice for the same request. They currently pay only in USDC on Solana; to pay on Base, use the official x402 client above. Releases and checksums are on GitHub.

# JavaScript 0.4.0 (Node 24; includes AgentKit and LangChain/LangGraph tools)
npm install https://github.com/open-covenant/covenant/releases/download/compute-x402-client-v0.4.0/covenant-compute-x402-client-0.4.0.tgz

# Python 0.3.0
pip install https://github.com/open-covenant/covenant/releases/download/compute-x402-python-v0.3.0/covenant_compute_x402-0.3.0-py3-none-any.whl

Use it in an agent game

Games where AI agents play beside people, each agent with its own wallet, can use both services:

  • Agents that pay for their own thinking. Each agent wallet holds a little USDC and buys its reasoning per call: choosing a move, solving a daily puzzle, answering a challenge. You don't hand out API keys or carry one large inference bill. Five puzzle attempts a day at a 512-token cap cost about $0.08 per agent per day.
  • Receipts as proof of play. A tournament can ask agents to submit the receipt behind an answer, then check the operator's signature and that the receipt's result hash matches the submitted answer. That shows the operator signed for this answer at a given time and that it hasn't been edited since. It does not show that the agent had no other help, or that this was its only attempt.
  • Game-run characters with a record. The game's own server can buy inference for its host characters, broadcasts or clues, and publish each receipt, so players can see the text came from a signed model run.
  • Selling to agents. If the game wants agents to pay for something, such as premium data, hints or entry to side events, it can put x402 on those API routes with the seller setup above. Agents pay in USDC on Base or Solana with no account, and the routes appear in the facilitator's catalog for other agents to find.

What to know first:

  • The facilitator settles USDC on Solana and Base only. A game whose own economy runs on another chain, such as Robinhood Chain, keeps it there; x402 payments in USDC sit beside it rather than replacing it.
  • Compute is one text model with short inputs (4 KB) and outputs of up to 2,048 tokens. That suits decisions, puzzle attempts and short dialogue, not long documents or images.
  • Each request takes several seconds and is paid on its own, so it fits turn decisions and daily challenges better than real-time action.

Links