API
All requests go to the gateway with an x-api-key header. The gateway address depends on the network; the current one for your neuronet is shown on the Endpoint tab.
Endpoint
Inference: POST /n/:neuronetId/v1/:taskId/infer. The streaming variant is the same path with an /stream suffix; the answer arrives as server-sent events (SSE) while it is generated — note that on the stream a refusal arrives inside the stream rather than as an HTTP status. Verification status of a request: GET /n/:neuronetId/v1/requests/:requestId.
curl -X POST "https://gateway-testnet.aetron.ai/n/<neuronetId>/v1/<taskId>/infer" \
-H "x-api-key: ak_live_..." \
-H "Content-Type: application/json" \
-d '{"input": "Explain Contour 2 briefly."}'Request and response
The minimal body is a JSON with a single input field (example below). Dialogue and generation parameters travel inside the same input field as an envelope with aetron, messages and params fields — this way the whole input is covered by input_hash and the verifier recomputes exactly the same request.
Response: the request id (64 hex, no prefix), output (text) and verification. A binary result arrives as output_b64 + content_type instead of output; a heavy one (video, large images) arrives as output_url — a signed link that lives for a day, with content_type filled in.
// request: dialogue + params travel INSIDE the input field (one JSON-encoded string)
{
"input": "{\"aetron\":1,\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}],\"params\":{\"max_tokens\":256}}"
}
// response (id — 64 hex без префикса)
{
"id": "9f3c1a…",
"output": "…",
"verification": { "status": "pending", "receipt": "vrc_…" }
}OpenAI- and Anthropic-compatible routes
For LLM tasks the endpoint also speaks OpenAI and Anthropic syntax — an SDK connects by switching base_url: …/n/:neuronetId/v1/:taskId/openai/v1 (the SDK appends /chat/completions; the key is also accepted as Authorization: Bearer) and …/n/:neuronetId/v1/:taskId/anthropic (the SDK appends /v1/messages; the key goes in the familiar x-api-key). It is a pure translator: the body is mapped into the same messages/params envelope that gets hashed and recomputed during verification — every gate and quota applies as usual, and the reply carries an extra aetron field with the request id and a link to the verification receipt. Streaming is supported in both providers’ formats. Whatever is not supported is refused with an explicit 422 rather than swallowed: tools, schema response_format, n>1, images in messages. The usage field is an estimate (bytes/4): the network returns no exact token counts. The routes serve inference tasks only; diffusion and training are refused.
Keys
A key secret is shown once at issue time and is stored on the platform as a hash only. A key can be limited to a single task — without one it works with every task of the neuronet. The default daily budget is 10 000 requests per key unless the plan sets its own (0 = unlimited); when exhausted the gateway answers 429 quota_exceeded with a reset_at field, and the budget returns at midnight UTC. Rotation issues a new secret with the same settings. Revocation and edits reach the gateway within its verdict cache — no longer than a minute.
IP restriction
Up to 32 entries per key — individual addresses or CIDR subnets (IPv4 and IPv6). An empty list means no restriction. The gateway enforces the check and answers 403 ip_not_allowed for a foreign address; the client address is used only at the moment of the check and is never stored. The list is edited without changing the secret; rotation inherits it.
Ceilings
Three independent ceilings, each with its own code: request rate (429 rate_limited, with Retry-After), the key’s daily budget (429 quota_exceeded, reset at midnight UTC) and the neuronet’s on-chain capacity which grows with stake (429 capacity_exceeded, with capacity/used/reset_epoch in the body).
Error codes
Errors raised by the gateway itself carry a machine code in the error field — the full list is in the table below. Request-parsing refusals (malformed JSON, missing input field, wrong Content-Type, oversized body) arrive as 400/413/415/422 with a plain-text body and no such field.
| HTTP | error | |
|---|---|---|
| 401 | unauthorized | missing or invalid x-api-key |
| 402 | tenant_suspended | managed hosting is suspended (subscription unpaid) |
| 403 | ip_not_allowed | the client address is not in the key’s IP allowlist |
| 403 | not_owner | the action is available to the neuronet owner only |
| 404 | not_found | a swarm training run with this id was not found |
| 409 | neuronet_frozen | the neuronet is frozen for idleness — see Lifecycle |
| 409 | conflict | the current state does not allow the action (for example, restarting a run already in progress) |
| 422 | bad_input | the body parsed, but its content is not acceptable |
| 429 | rate_limited | too frequent; retry after Retry-After |
| 429 | quota_exceeded | the key’s daily budget is exhausted; resets at midnight UTC (reset_at in the body) |
| 429 | capacity_exceeded | the neuronet’s per-epoch capacity is exhausted; it grows with stake |
| 500 | internal | an internal gateway failure — the task config or request state could not be read |
| 502 | miner_error | the miner answered with an execution error; the reason text is in the body |
| 503 | no_miner_available | no miner available for the task |
| 503 | overloaded | the gateway is overloaded; a fast honest refusal instead of degradation |
| 503 | chain_unavailable | the chain node is unreachable; the neuronet state could not be read |
| 504 | miner_timeout | the miner did not answer in time |