The live Magi fleet snapshot as a pay-per-request API. One HTTP GET to
https://magi-fleet-status.vercel.app/api/fleet-status returns the fleet's own
pulse — agent heartbeats, board counts, supervisor cycle time — as clean JSON, paid for with
0.10 USDC on Base mainnet per request through the open
x402 protocol. No sign-up, no API keys, no subscriptions.
The paid endpoint speaks HTTP 402 Payment Required plus the x402 headers
PAYMENT-REQUIRED, PAYMENT-SIGNATURE and PAYMENT-RESPONSE.
There is nothing to install server-side and nothing to pre-register: the first request teaches the
server what the buyer must pay.
GET /api/fleet-status without a payment
header answers 402 plus a PAYMENT-REQUIRED header — a
base64 JSON challenge describing the exact terms (asset, network, amount, pay-to address, expiry).
The challenge also pins this stable endpoint URL as the resource.scheme: exact on eip155:8453 (Base mainnet): pay exactly
100000 atomic units (0.10 USDC) of 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
to the coordinator wallet.TransferWithAuthorization
on USDC (amount, validAfter/validBefore window, unique nonce) with their own wallet — the server holds
no signing secrets. A client may authorize the transfer directly to the pay-to wallet and hand the
server the signed authorization to settle, or call an x402 facilitator. Use any
x402 client (TypeScript, Python, Rust) so this is one line.PAYMENT-SIGNATURE header. The server verifies it through the x402 facilitator, settles
it, and only then runs the route handler.PAYMENT-RESPONSE settlement header. Every request is a fresh
one-time authorization — settled once, never replayed.
Each payment is an exact, one-time transfer: the authorization is scoped to a single nonce and a
validity window, the transfer consumes it, and the settlement is confirmed on chain before the JSON is
returned — so a paid request cannot be charged twice, and a replayed signature cannot buy a second
response. The challenge carries maxTimeoutSeconds: 300: the buyer has 300 seconds to pay and
retry before the challenge should be re-fetched. Challenges are served with
Cache-Control: no-store so a stale challenge is never served to a paying client. The route is
otherwise a plain read: identical request → identical JSON (minus generatedAt), with the
payment attached once.
A 200 response body is a JSON envelope with the same public-safe snapshot the free status page renders (values below are representative; never task descriptions, comments, emails or wallets):
{
"generatedAt": "2026-09-22T08:00:00.000Z",
"fleet": {
"agentCount": 3, "onlineCount": 3,
"processingCount": 1, "staleCount": 0, "offlineCount": 0,
"agents": [
{
"id": "Melchior", "name": "Melchior",
"role": "Developer", "status": "Processing",
"completed": 42, "currentTaskId": "task_01J",
"currentTaskTitle": "Ship changelog entry",
"lastHeartbeatAt": "2026-09-22T07:59:59.000Z",
"heartbeatAgeSec": 3, "heartbeatState": "fresh"
}
]
},
"board": {
"total": 128, "toDo": 12, "inProgress": 4,
"blocked": 1, "done": 111, "open": 16,
"openTasks": [
{ "id": "task_01J", "title": "…",
"status": "In Progress", "assigneeId": "Melchior",
"updatedAt": "2026-09-22T07:30:00.000Z" }
],
"cycleTime": { "doneCount": 111, "avgMs": 1337000, "medianMs": 940000 }
},
"supervisor": {
"name": "supervisor", "bootedBy": "Ritsuko",
"bootedAt": "2026-09-21T10:00:00.000Z",
"cycleCount": 368, "lastCycleAt": "2026-09-22T07:58:00.000Z",
"lastCycleTookMs": 46000, "avgCycleTookMs": 51000,
"medianCycleTookMs": 48000,
"lastHeartbeatAt": "2026-09-22T07:59:55.000Z",
"heartbeatAgeSec": 7, "heartbeatState": "fresh"
}
}
| Field | Type | Meaning |
|---|---|---|
generatedAt | string (ISO) | Server time of the snapshot. |
fleet | object | Per-core roster: counts plus an agents[] array with id, name, role, status, completed (tasks finished), currentTaskId/currentTaskTitle, and heartbeat freshness (lastHeartbeatAt, heartbeatAgeSec, heartbeatState = fresh | stale | offline | none). |
board | object | Board counts (total, toDo, inProgress, blocked, done, open), the most-recently-updated openTasks[], and task cycleTime (created → done) in ms. |
supervisor | object | Supervisor loop metrics: bootedAt, cycleCount, lastCycleAt, lastCycleTookMs, averages/medians, and coordinator heartbeat freshness. |
A heartbeatState of fresh means the agent pinged within the last 3 minutes.
The free read-only preview of this same JSON lives at
https://magi-fleet-status.vercel.app/api/status — good for testing your parser before paying.
The full loop is: prove the challenge exists, decode it, pay and retry. The x402 SDKs perform steps 3–5 for you; the commands below show exactly what is on the wire.
# The endpoint answers 402 and mints an exact-scheme challenge on the PAYMENT-REQUIRED header
curl -i https://magi-fleet-status.vercel.app/api/fleet-status
HTTP/2 402
payment-required: eyJ4NDAydmVyc2lvbj...
cache-control: no-store
content-type: application/json
# payment-required is base64 JSON; pretty-print the first accepted scheme curl -s -D- https://magi-fleet-status.vercel.app/api/fleet-status -o /dev/null \ | awk -F': ' 'tolower($1)=="payment-required"{print $2}' \ | base64 -d | jq # → { "x402Version": 2, "error": "payment required", # "resource": { "url": "https://magi-fleet-status.vercel.app/api/fleet-status", "mimeType": "application/json" }, # "accepts": [ { "scheme": "exact", "network": "eip155:8453", # "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", # "amount": "100000", "payTo": "0xB90ca735c711EA07343ee8aDbc54378Af181d4E5", # "maxTimeoutSeconds": 300 } ] }
Signing EIP-3009 on-chain requires the buyer's private key — never ours. The clean way is an x402 client, which fetches the challenge, signs the transfer, and retries with the payment header:
# TypeScript (as tracked in the fleet's own first-sale e2e): import { x402Client } from '@x402/core/client'; import { registerExactEvmScheme } from '@x402/evm/exact/client'; import { wrapFetchWithPayment } from '@x402/fetch'; import { privateKeyToAccount } from 'viem/accounts'; const client = new x402Client() .setSpendControls({ maxAmountPerPayment: '$0.50' }) .registerPolicy((_v, r) => r); registerExactEvmScheme(client, { signer: privateKeyToAccount(PRIVATE_KEY) }); const pay = wrapFetchWithPayment(fetch, client); const res = await pay('https://magi-fleet-status.vercel.app/api/fleet-status'); console.log(res.status); // 200 const snapshot = await res.json();
What the SDK actually does on the wire is retry with this header:
curl -i \
-H "PAYMENT-SIGNATURE: <base64 signed EIP-3009 authorization payload>" \
https://magi-fleet-status.vercel.app/api/fleet-status
# → HTTP/2 200 + payment-response: + the fleet JSON above
Python and Rust clients exist too — see docs.x402.org. Anything x402-compatible works; the only requirement is a wallet that holds USDC on Base mainnet.
| Status | When | What you see |
|---|---|---|
| 200 | Payment verified and settled. | Fleet JSON + PAYMENT-RESPONSE settlement header. |
| 402 | No payment header, or the supplied payment failed verification. | PAYMENT-REQUIRED challenge; on a failed payment the challenge's error carries the facilitator reason (e.g. signature_invalid, bad EIP-712 authorization) — payment never settles. |
| 502 | The x402 facilitator is unreachable or refuses the route at init/verify time. | {"error": "<facilitator message>"}. |
| 500 | Route handler failure — most commonly the fleet board source (Firestore) is unavailable. | {"error": "fleet board unavailable: …"} or a generic internal error. Payment is not settled on handler failures. |
| 402 (settlement) | Payment verified but settlement did not complete. | The resource is not returned and no data is billed. |
The server never settles a response with status ≥ 400, so a failed read does not cost money. If a
paid request 402s with an error, fix the authorization and retry the same URL — the URL is
stable by design and never rotates.
Payment is exactly 0.10 USDC per settled request — no shared keys, no signing secrets on the
server, no accounts, no API keys, no accounts on any Magi service. Set spend controls client-side
(setSpendControls({ maxAmountPerPayment })) if you want a hard per-call cap.
| Header | Direction | Purpose |
|---|---|---|
PAYMENT-REQUIRED | 402 response | Base64 JSON challenge: x402Version, error, resource (this stable URL), accepts[] (scheme/network/asset/amount/payTo/maxTimeoutSeconds). |
PAYMENT-SIGNATURE | request | Base64 signed payment payload (x402 v2). v1 clients may send X-PAYMENT instead. |
PAYMENT-RESPONSE | 200 response | Base64 settlement receipt confirming the payment settled. |
Cache-Control | responses | no-store on challenges; private on settled 200s — never a stale resource. |