Quickstart
Base URL: /v1. There are two ways to pay for a call, and both reach the same models at the same price.
- Prepaid key. Deposit once, get a key that starts with
off_sk_, and use it as a normal bearer token. Best for anything built on an OpenAI SDK. - Pay per call. Send no key. The gateway replies
402with a price and an x402 client pays it. Best for autonomous agents that hold their own wallet.
curl /v1/chat/completions \ -H "Authorization: Bearer $SEALANE_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "deepseek-v4-flash", "stream": true, "messages": [{"role": "user", "content": "Hello"}]}'
List the models with GET /v1/models, or see them on the models page.
Prepaid keys
A key is created by a deposit and spends down per call. There are no accounts: the key is the account, and the Solana wallet that paid for it is its owner. The easiest way to make one is the dashboard. The same thing over the API:
POST /v1/keys {"amount_usd": 5} # x402 deposit, returns the key once
POST /v1/keys/topup {"amount_usd": 5} # x402 deposit + Bearer, adds balance
GET /v1/keys/me # balance and recent usage
DELETE /v1/keys/me # revoke, refund what is leftHow a keyed call is charged
Before the call is served, the worst case (your full input plus max_tokens of output) is held against the balance. After it finishes, the hold is settled down to the real token count. A key can never spend more than it holds, even with many calls at once.
If you leave max_tokens out it defaults to 8192. If the balance cannot cover the budget you asked for, the budget is lowered to what it can.
The charge for each call comes back in the X-Sealane-Charge-USD response header.
Pay per call
With no key, a request is paid for on the spot using x402. The flow is two requests:
POST /v1/chat/completions # 402, price in PAYMENT-REQUIRED POST /v1/chat/completions + PAYMENT-SIGNATURE # settles, then 200 + PAYMENT-RESPONSE
max_tokens is required here. The price in the 402 is a ceiling: your full input plus max_tokens of output. Your client signs that amount, it settles onchain, and the call is served only after settlement.
Refunds
When the call ends, the real charge is worked out from actual usage. The difference between what you signed and what you used is queued as a refund to the paying wallet, on the network you paid on. A failed call or an empty completion is refunded in full. Small refunds are batched and sent together.
Refunds mean extra onchain transfers. If you make many calls, a prepaid key is cheaper to run and leaves a smaller onchain trail: one deposit instead of a payment and a refund per call.
Client
import { createKeyPairSignerFromBytes } from "@solana/kit";
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactSvmScheme } from "@x402/svm/exact/client";
import bs58 from "bs58";
const signer = await createKeyPairSignerFromBytes(bs58.decode(process.env.AGENT_KEY));
const client = x402Client.fromConfig({
// Solana mainnet-beta, as a CAIP-2 id. The facilitator pays the transaction fee.
schemes: [{ network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d", client: new ExactSvmScheme(signer) }],
});
const pay = wrapFetchWithPayment(fetch, client);
const res = await pay("/v1/chat/completions", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
model: "gpt-oss-120b",
max_tokens: 512, // required: it bounds the amount you sign
messages: [{ role: "user", content: "Summarise this wallet history." }],
}),
});A machine-readable description of every paid endpoint is at /.well-known/x402.
Networks
Every 402 lists each stablecoin below in accepts[] at the same amount, all on Solana mainnet-beta (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d). Pay with whichever one your wallet holds. All three have 6 decimals. A payment is an SPL transfer that your wallet signs and the facilitator submits as fee payer, so the payer needs no SOL.
| Network | CAIP-2 | Asset | Paid from | Asset contract |
|---|---|---|---|---|
| Loading from the gateway… | ||||
This table is read live from GET /networks. A deposit is refunded on the network it arrived on.
Solana specifics
The payer's token account must already exist; the gateway's receiving token account is created by us. The client signs a versioned transaction that contains only one TransferChecked instruction to the payTo account for the exact amount, with the facilitator as fee payer. The gateway rejects any transaction that carries other instructions or a different mint.
Confirmation is confirmed commitment, usually under two seconds. PYUSD uses the Token-2022 program; the client picks the right program from the mint. Receipts link to the signature on Solscan.
Receipts
Every model runs in a GPU enclave (Intel TDX with a confidential NVIDIA GPU) on hardware we do not operate. Each response carries three headers so you can check that for yourself:
X-Sealane-Receipt: the receipt id. It equals the completionid.X-Sealane-Receipt-URL: where to fetch the signed receipt,GET /v1/private/receipts/:id. It holds hashes and timestamps, never content, and needs no key.X-Sealane-Attestation: the enclave's public attestation report. The key that signs the receipt is published in it.
We cannot forge a receipt: it is signed by a key that only exists inside the attested enclave.
What this does and does not cover
The enclave operator cannot read your prompts or outputs. The Sealane gateway does see the request in memory while forwarding it, and does not store it. Removing the gateway from that path, by encrypting on the client to the enclave key, is planned and not available yet.
MCP server
POST /mcp is a remote MCP server. There is nothing to install: add the URL with a prepaid key as the bearer.
claude mcp add --transport http sealane /mcp \
--header "Authorization: Bearer $SEALANE_KEY"Tools: list_models (no key needed), ask, compare (the same prompt to several models) and balance. Tool calls are billed exactly like direct API calls. Pay per call is not available over MCP, because a remote server cannot sign for your wallet.
Errors
API errors use the OpenAI shape, {"error": {"message", "type", "code"}}. Payment problems use the x402 shape with a code.
| Status | Code | What to do |
|---|---|---|
| 400 | max_tokens_required | Set max_tokens on pay-per-call requests. |
| 401 | invalid_api_key | Check the key. Closed keys stop working at once. |
| 402 | insufficient_balance | Top up the key or lower max_tokens. |
| 402 | terms_mismatch | Sign exactly the amount, asset and recipient from the 402. |
| 402 | payment_replayed | That payment was already used. Sign a new one. |
| 404 | model_not_found | Use an id from GET /v1/models. |
| 429 | model_overloaded | Retry in a few seconds. |
| 502 | upstream_error | Retry shortly. A paid call that fails is refunded. |