Dagon Inference / Pay-per-request LLM API with x402 (USDC on Solana)
Pay-per-request LLM API with x402 (USDC on Solana)
Published · Last updated
Send a request to https://inference.dagon.so/v1/chat/completions, /v1/responses or /v1/messages with no API key. The gateway answers 402 Payment Required with x402 payment requirements (versions 1 and 2, exact scheme, USDC on Solana mainnet). Your agent signs a USDC transfer, repeats the request with it in X-PAYMENT or PAYMENT-SIGNATURE, and gets the model's answer plus a prepaid key in x-dagon-key that holds whatever the request did not spend. No account, no email, and no SOL: the gateway pays the network fee. A small request costs at least $0.5; one payment can be at most $1,000.
How does the x402 flow work?
- Send the request as usual, without
Authorization. The gateway validates it and prices its maximum cost (prompt estimate plus output cap), then answers402with codepayment_required. The body keeps the usual OpenAI or Anthropicerrorobject and adds the x402 v1 fieldsx402Versionandaccepts; thePAYMENT-REQUIREDheader carries the same requirements as x402 v2 (base64 JSON). - Your client signs, but does not send, a Solana transaction: one SPL Token
TransferCheckedof the stated amount of USDC from the wallet's own USDC account to the treasury9rMdbu4KdLWH2nPXbzhm9HTKaibGZ2ckakQbW1wPh6KK(USDC accountE6dUxbCSJ3ygHSuT5DrjLDJediPzHiKQy2nJHb115nfg), withextra.feePayeras the fee payer. - It repeats the same request with the base64 payment payload in
X-PAYMENT(v1) orPAYMENT-SIGNATURE(v2). - The gateway checks the transaction, refuses blocked locations, screens the paying wallet against the OFAC SDN list, co-signs as fee payer, simulates, broadcasts and waits for confirmation (usually seconds), then serves the request from the payment.
- The response carries
PAYMENT-RESPONSEandX-PAYMENT-RESPONSE(base64 JSON withsuccess,transaction,network,payer,amount),x-dagon-transaction(the signature) and, for a keyless payment,x-dagon-key.
Standard x402 clients do all of this for you: @x402/fetch or @x402/axios with @x402/svm, the Python x402 package, or the v1 x402-fetch and x402-axios.
What does the 402 response look like?
This is the answer to a small keyless chat request (its maximum cost is under the minimum, so the minimum of $0.5, 500000 USDC base units, is asked). On /v1/messages the error object has the Anthropic shape instead.
HTTP/1.1 402 Payment Required
Content-Type: application/json
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Mi... (base64 JSON, below)
Link: <https://inference.dagon.so/terms>; rel="terms-of-service"
Cache-Control: no-store
{
"x402Version": 1,
"accepts": [{
"scheme": "exact",
"network": "solana",
"maxAmountRequired": "500000",
"resource": "https://inference.dagon.so/v1/chat/completions",
"description": "One abliterated-model-large-flash request on Dagon, prepaid at its maximum cost. The unspent rest stays as credit on the key returned once in x-dagon-key and is not refunded; reuse that key. Terms: https://inference.dagon.so/terms",
"mimeType": "application/json",
"payTo": "9rMdbu4KdLWH2nPXbzhm9HTKaibGZ2ckakQbW1wPh6KK",
"maxTimeoutSeconds": 60,
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"extra": { "feePayer": "4UZVmNWoetLmDeQnfFFCYrFuN7epN6WgchiDxJ6VVA52" }
}],
"error": {
"message": "Pay for this request with x402 (USDC on Solana; requirements in `accepts` and the PAYMENT-REQUIRED header), or send an API key as 'Authorization: Bearer <key>'.",
"type": "billing_error",
"param": null,
"code": "payment_required"
}
}Decoded, the PAYMENT-REQUIRED header is the x402 v2 object:
{
"x402Version": 2,
"error": "Pay for this request with x402 ...",
"resource": { "url": "https://inference.dagon.so/v1/chat/completions", "description": "One abliterated-model-large-flash request on Dagon, ...", "mimeType": "application/json" },
"accepts": [{
"scheme": "exact",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"amount": "500000",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"payTo": "9rMdbu4KdLWH2nPXbzhm9HTKaibGZ2ckakQbW1wPh6KK",
"maxTimeoutSeconds": 60,
"extra": { "feePayer": "4UZVmNWoetLmDeQnfFFCYrFuN7epN6WgchiDxJ6VVA52" }
}]
}Amounts are USDC base units (millionths of a dollar). The fee payer above is the production one; it is also listed on official domains and payment addresses. Check the treasury in full against official domains and payment addresses before your agent signs anything.
TypeScript (@x402/fetch and @x402/svm)
// 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 file 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 }),
});
const reply = await res.json();
console.log(reply.choices?.[0]?.message?.content ?? reply.error);
// Keep this key: it holds what the request did not spend. Send it as a Bearer key next time.
const key = res.headers.get("x-dagon-key");The wrapper reads the 402, signs the transfer with the wallet and retries once. For streaming, set "stream": true as usual; the stream starts after the payment confirms.
Python (x402 with httpx)
# pip install "x402[httpx,svm]" then: python pay_per_request.py
import asyncio
import os
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.svm import KeypairSigner
from x402.mechanisms.svm.exact.register import register_exact_svm_client
async def main():
# Refuse any single payment above $1; raise it for large requests.
client = x402Client().set_spend_controls({"max_amount_per_payment": "$1"})
# Base58 secret key of a wallet holding USDC (no SOL needed).
register_exact_svm_client(client, KeypairSigner.from_base58(os.environ["SOLANA_PRIVATE_KEY"]))
# Settlement waits for Solana confirmation: allow a long timeout.
async with x402HttpxClient(client, timeout=120) as http:
r = await http.post("https://inference.dagon.so/v1/chat/completions", json={
"model": "abliterated-model-large-flash",
"messages": [{"role": "user", "content": "Hi"}],
"max_tokens": 200,
})
await r.aread()
print(r.status_code, r.json())
# Keep this key: it holds what the request did not spend.
print("x-dagon-key:", r.headers.get("x-dagon-key"))
asyncio.run(main())Any OpenAI or Anthropic SDK works for the requests after the first: pass the key from x-dagon-key as the API key and the base URL https://inference.dagon.so/v1.
Why reuse 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 as credit on a gk_ prepaid key, returned once in x-dagon-key. It is not refunded to the wallet, so keep the key and send it as Authorization: Bearer gk_... (or x-api-key) on the next requests: they draw that balance down and need no payment.
The key is tied to the paying wallet: every keyless payment from one wallet credits the same key and returns the same secret, so an agent that loses the header gets the key again with its next keyless payment. When the key runs short, the gateway answers 402 insufficient_credits asking for a top-up of at least $1 (or the shortfall, if larger); pay it with the key still in Authorization and that key is credited. Lease keys (lk_) cannot be topped up this way.
Does my agent need SOL?
No. The 402 names the gateway's fee payer in extra.feePayer. Your agent builds the transaction with that address as fee payer and signs only as the owner of the USDC; the gateway adds the fee payer's signature and pays the network fee. The wallet needs USDC in its own USDC token account and nothing else. To keep the sponsored fee bounded, a sponsored payment may set at most 200,000 compute units and a priority price of at most 50,000 microlamports per unit, and the fee payer may not appear in any instruction.
What are the limits?
- Keyless request: pays its maximum cost, at least $0.5. Top-up of a key: the shortfall, at least $1.
- One payment: at most $1,000, and at most $0.01 over the stated amount.
- Per key: at most $2,000 of paid credit in any 24 hours, across x402, wallet purchases and checkout.
- The transaction: legacy or version 0, no address lookup tables, at most 7 instructions, only compute budget, one USDC
TransferChecked, and memo or wallet-added Lighthouse instructions; the transfer authority must be a key pair that signs (no multisig). - Each transaction is credited once, and never also to a checkout.
- Solana mainnet only. For other chains, use hosted USDC checkout.
Where is x402 payment refused?
Payments are checked before anything is signed or broadcast. A request from a location where the service is not offered gets 451 location_blocked; the check uses the caller's IP address. A transaction signed by a wallet on the OFAC SDN list gets 403 payment_refused, nothing is broadcast, and a key being topped up is disabled. While the location table or the sanctions list is loading, payments get 503 with Retry-After. We do not monitor or log your content, and the acceptable use policy applies: use it lawfully and only against systems and people you own or have permission to test. We suspend keys that break it.
Troubleshooting by error code
402 payment_required: no key and no payment. Pay whatacceptsasks, or send a key.402 insufficient_credits: the key is short of this request's maximum cost. Pay the top-up inaccepts, lowermax_tokens, or fund the key another way.402 invalid_exact_svm_payload_amount_mismatch: the transfer is below the amount, more than $0.01 over it, or over $1,000. Sign a new payment for exactly the stated amount.402 invalid_exact_svm_payload_recipient_mismatchor_mint_mismatch: pay USDC (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v) to the treasury's USDC account.402 invalid_exact_svm_payload_transaction_fee_payer_transferring_funds,_excessive_signers,_instructions_compute_limit_instruction_too_high,_compute_price_instruction_too_high: build the transaction as the x402 SDKs do, withextra.feePayeras fee payer only.402 invalid_exact_svm_smart_wallet_alt_resolution_not_available: address lookup tables are not accepted.402 invalid_exact_svm_transaction_simulation_failed: usually not enough USDC, or no USDC token account. ThePAYMENT-RESPONSEheader has the reason.402 invalid_exact_svm_transaction_failed: it failed on chain or expired before landing. Sign a new payment with a recent blockhash.402 duplicate_settlement: this transaction was already presented. Sign a new one.402 settlement_pending: broadcast but not confirmed in time. Retry the same request with the same payment header and the key fromx-dagon-keyafterRetry-After; it is credited once it lands.402 paid_daily_cap_exceeded: the key received $2,000 of paid credit in the last 24 hours. Try later.400 invalid_exact_svm_payload_transaction_could_not_be_decoded,_unsupported_scheme,_network_mismatch: the header is not a base64 x402 payload forexacton Solana mainnet.400 not_topup_key: lease keys cannot be topped up with x402.403 payment_refused,451 location_blocked: see above.503 payment_unavailable,sanctions_unavailable,geo_unavailable: try again afterRetry-After; nothing was charged.
What are the other ways an agent can pay?
- x402 per request (this page): no key, no setup, pays as it goes.
- Wallet top-up in two calls:
POST /v1/credits/purchasereturns a USDC transaction, the agent signs and sends it, andPOST /v1/credits/purchase/confirmcredits the key. See buy credits from an agent wallet. - MCP server: the
mcp/folder of the gateway repository is a local stdio MCP server with tools to list models, create a key, buy credits from a wallet and chat. It is not published to npm; run it from a checkout.
A person paying with a browser wallet uses hosted USDC checkout instead.
Common questions
Can an AI agent pay for LLM API calls itself?
Yes. With x402 an agent that controls a Solana wallet holding USDC pays for each request inside the HTTP exchange: no account, email, browser or API key. The first paid response returns a prepaid key the agent can keep using.
Which x402 versions, schemes and networks are supported?
x402 versions 1 and 2, the exact scheme, USDC on Solana mainnet (solana in v1, solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp in v2). Other chains and tokens are not accepted over x402.
Is a facilitator involved?
No. The gateway verifies and settles payments itself, so the location check and the OFAC screen run before anything is signed. Clients need no facilitator configuration.
Is the unspent amount refunded?
No. It stays as credit on the key returned in x-dagon-key, which the same wallet gets back on every keyless payment. Spend it by sending that key.
Which models can I pay for this way?
Every listed model: abliterated-model-large-v2, deepseek-v4.1-flash-abliterated, glm-5.3-flash-abliterated, abliterated-model-large-flash and abliterated-model. Prices are on the pricing page and at GET https://inference.dagon.so/v1/models.