Dagon InferenceDocs Console

Payments

x402 pay per request

The inference endpoints speak x402 versions 1 and 2, exact scheme, USDC on Solana mainnet. An agent with a wallet holding USDC pays inside the HTTP exchange, and the gateway pays the network fee.

On this page

The flow

  1. Send the request with no key. The gateway validates and prices it, then answers 402 payment_required. The body keeps the usual error object and adds the x402 v1 fields x402Version and accepts; the PAYMENT-REQUIRED header carries the v2 requirements (base64 JSON).
  2. Sign, without sending, one SPL Token TransferChecked of the stated USDC amount from your own USDC account to the treasury 9rMdbu4KdLWH2nPXbzhm9HTKaibGZ2ckakQbW1wPh6KK, with extra.feePayer as fee payer.
  3. Repeat the request with the base64 payload in X-PAYMENT (v1) or PAYMENT-SIGNATURE (v2).
  4. The gateway checks the transaction, the location and the OFAC list, co-signs as fee payer, broadcasts, waits for confirmation and serves the request.
  5. The response carries PAYMENT-RESPONSE / X-PAYMENT-RESPONSE, x-dagon-transaction and, for a keyless payment, x-dagon-key.

The 402 response

HTTP
HTTP/1.1 402 Payment Required
Content-Type: application/json
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Mi... (base64 JSON, x402 v2)
Link: <https://inference.dagon.so/terms>; rel="terms-of-service"

{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "solana",
    "maxAmountRequired": "500000",
    "resource": "https://inference.dagon.so/v1/chat/completions",
    "mimeType": "application/json",
    "payTo": "9rMdbu4KdLWH2nPXbzhm9HTKaibGZ2ckakQbW1wPh6KK",
    "maxTimeoutSeconds": 60,
    "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "extra": { "feePayer": "4UZVmNWoetLmDeQnfFFCYrFuN7epN6WgchiDxJ6VVA52" }
  }],
  "error": { "message": "...", "type": "billing_error", "param": null, "code": "payment_required" }
}

Amounts are USDC base units (millionths of a dollar). In v2 the network is solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp and the amount field is amount. Check the treasury against official addresses before relying on it.

Clients

// npm install @x402/fetch @x402/svm @solana/kit
import { readFileSync } from "node:fs";
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactSvmScheme, toClientSvmSigner } from "@x402/svm";
import { createKeyPairSignerFromBytes } from "@solana/kit";

// A solana-keygen JSON keypair for a wallet holding USDC (no SOL needed).
const secret = Uint8Array.from(JSON.parse(readFileSync(process.env.SOLANA_KEYPAIR ?? "", "utf8")));
const signer = toClientSvmSigner(await createKeyPairSignerFromBytes(secret));
const pay = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", client: new ExactSvmScheme(signer) }],
});

const res = await pay("https://inference.dagon.so/v1/chat/completions", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ model: "abliterated-model-large-flash", messages: [{ role: "user", content: "Hi" }], max_tokens: 200 }),
});
console.log(await res.json());
// Keep this key: it holds what the request did not spend.
const key = res.headers.get("x-dagon-key");

The v1 clients x402-fetch and x402-axios work too, with createSigner("solana", privateKey). More detail: the x402 guide.

Keep the key in x-dagon-key

A keyless payment buys the request's maximum cost, at least $0.5. What the request does not spend stays on a new gk_ key returned once in x-dagon-key; it is not refunded to the wallet. Send that key on the next requests. When it runs short, the gateway answers 402 insufficient_credits asking for a top-up of at least $1 (or the shortfall); pay it with the key still in Authorization and that key is credited.

Limits

  • One payment: at most $1,000, and at most $0.01 over the stated amount.
  • At most $2,000 of paid credit per account in 24 hours (per paying wallet without a key).
  • The transaction: legacy or version 0, no address lookup tables, at most 7 instructions: compute budget, exactly one USDC TransferChecked and memo. A sponsored payment may set at most 50,000 compute units and 10,000 microlamports per unit.
  • A wallet may have one sponsored payment in flight (429 sponsor_in_flight).

Error codes

AnswerWhat to do
402 payment_requiredPay what accepts asks, or send a key.
402 insufficient_creditsPay the top-up, lower max_tokens, or fund the key another way.
402 invalid_exact_svm_payload_amount_mismatchSign a new payment for exactly the stated amount.
402 invalid_exact_svm_payload_recipient_mismatch, …_mint_mismatchPay USDC to the treasury's USDC account.
402 invalid_exact_svm_transaction_simulation_failedUsually not enough USDC, or no USDC token account. PAYMENT-RESPONSE has the reason.
402 duplicate_settlementThis transaction was already presented. Sign a new one.
402 settlement_pendingRetry the same request with the same payment header (and the key from x-dagon-key) after Retry-After.
409 invalid_transaction_stateThe network already knew this transaction before it reached us. Sign a new one and do not broadcast it.
403 payment_refused, 451 location_blockedSanctioned wallet, or a location where the service is not offered.
503 sanctions_unavailable, geo_unavailable, fee_payer_unavailable, sponsorship_unavailableRetry after Retry-After; nothing was charged.

Last updated