Download OpenAPI specification:
0G Router is an API gateway between users and the decentralized 0G Compute Provider network. It provides unified access, fee collection, and intelligent routing for AI inference services.
User funds live in the shared 0G Payment Layer (PL) vault — a multi-app funding pool that other 0G products also draw from. Router does not drain a user's full vault balance up front; it pulls small amounts on demand into its own ledger as inference is consumed.
As a result, the /v1/account/balance endpoint returns the Router ledger only (deposit_balance + credit_balance). It deliberately excludes the PL vault, because vault balance is shared across consumer apps and is not yet committed to Router.
/balance vs /fundsIf you just want one display balance that already combines both sides, call /v1/account/funds. Router does the aggregation server-side and returns a net total = (deposit + credit − pending_charge) + vault_balance, plus the breakdown. Unlike /balance's total_balance (Router-ledger-only, always ≥ 0), /funds.total includes the full vault and may be negative when the user owes Router (pending_charge exceeds available funds) — render that as "owed to Router".
Use /v1/account/balance (not /funds) for settlement / SDK / mgmt-key integrations that depend on the Router-ledger-only, ≥ 0 figure. And note /funds.total is a wallet-display number: it is not the admission figure — the "can I submit a request" calculation below applies vault_ratio and is computed separately.
An inference request is admitted whenever either side has enough funds:
min_cost, orvault_balance × vault_ratio − pending_charge >= min_cost (deferred path; the shortfall is recorded as pending_charge and cleared from the next PL pull).Otherwise the request returns 402 insufficient_balance.
After a user's first successful inference charge, the account becomes pull-eligible. A background worker then keeps the Router ledger topped up from the PL vault:
| Parameter | Mainnet value | Meaning |
|---|---|---|
| Scan interval | 3 s | How often Router checks each pull-eligible account |
| Low watermark | 0.1 0G | Pull triggers when effective Router balance drops below this |
| High watermark | 0.5 0G | Target balance after a pull (≈ amount pulled per cycle) |
| Vault ratio | 0.5 | Only 50% of the PL vault counts toward admission (safety margin for the shared pool) |
| min_cost | 0.00001 0G | Minimum cost a single request must be able to cover |
Accounts that have only deposited to the vault but never sent an inference request will not trigger a pull.
To gate a submit button before the first request, combine both sides:
available = router.total_balance + max(0, vault_balance × vault_ratio − pending_charge)
Use vault_ratio from the table above (0.5 on mainnet). Allow submission when available > 0. There is no need to mirror the min_cost floor on the client — Router enforces it at admission time and returns 402 if the request cannot be covered.
Returns a single aggregated view of the caller's funds so clients don't have to combine /account/balance (Router ledger) with the on-chain PaymentVault.balanceOf themselves.
total = router.subtotal + payment_layer.balance, where router.subtotal = deposit + credit − pending_charge (the net Router-ledger position). total is the user's net spendable funds and may be negative when outstanding debt exceeds available funds — render the shortfall as "owed to Router". This differs from /account/balance's total_balance, which keeps a ≥0 contract for settlement / SDK callers and does NOT subtract pending_charge.
payment_layer.balance is the shared Payment Layer vault balance (shared_across_products: true — the vault is a pool across 0G apps, not owned exclusively by Router). queried_at is when that balance was actually read from chain; it is cached (~10s), so on a cache hit it can be up to that TTL in the past — treat it as the value's as-of time, not the request time.
For the Router-ledger-only view that settlement / SDK / mgmt-key integrations depend on, use /account/balance instead.
{- "address": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
- "payment_layer": {
- "balance": "7086440000000000000",
- "queried_at": "2026-05-25T16:21:00Z",
- "shared_across_products": true
}, - "router": {
- "credit": "3560000000000000",
- "deposit": "300000000000000000",
- "pending_charge": "0",
- "subtotal": "303560000000000000"
}, - "total": "7390000000000000000"
}Get usage statistics broken down by day for current user, with optional filters
| api_key_id | string Filter by API key ID |
| source | string Filter by source: 'wallet' (JWT/browser), 'api_key' (any API key), or omit for all |
| start_date | string Start date (YYYY-MM-DD, inclusive) |
| end_date | string End date (YYYY-MM-DD, inclusive) |
| trust_mode | string Filter by trust tier: 'verified' | 'private'. Omit for all tiers. |
{- "data": [
- {
- "canonical_id": "glm-5",
- "cost": "150000000000000",
- "date": "2024-01-15",
- "input_tokens": 8000,
- "model_id": "glm-5",
- "output_tokens": 4345,
- "request_count": 42,
- "trust_mode": "verified"
}
], - "object": "list"
}Get usage history for current user, with optional filters
| limit | integer Default: 20 Limit number of records |
| offset | integer Default: 0 Offset for pagination |
| model_id | string Filter by model ID |
| api_key_id | string Filter by API key ID |
| source | string Filter by source: 'wallet' (JWT/browser), 'api_key' (any API key), or omit for all |
| start_date | string Start date (YYYY-MM-DD, inclusive) |
| end_date | string End date (YYYY-MM-DD, inclusive) |
| trust_mode | string Filter by trust tier: 'verified' | 'private'. Omit for all tiers. |
{- "data": [
- {
- "api_key_id": "abc12345",
- "cached_tokens": 40,
- "canonical_id": "glm-5",
- "cost": "150000000000000",
- "created_at": "2024-01-15T10:30:00Z",
- "credit_used": "50000000000000",
- "deposit_used": "100000000000000",
- "id": 1,
- "input_tokens": 100,
- "model_id": "qwen-2.5-7b-instruct",
- "output_tokens": 50,
- "provider_address": "0x1234...",
- "request_id": "req_abc123",
- "trust_mode": "verified"
}
], - "limit": 20,
- "object": "list",
- "offset": 0,
- "total": 100
}Get usage statistics for current user, optionally filtered by API key and date range
| api_key_id | string Filter by API key ID |
| source | string Filter by source: 'wallet' (JWT/browser), 'api_key' (any API key), or omit for all |
| start_date | string Start date (YYYY-MM-DD, inclusive) |
| end_date | string End date (YYYY-MM-DD, inclusive) |
| trust_mode | string Filter by trust tier: 'verified' | 'private'. Omit for all tiers. |
{- "completion_tokens": 4345,
- "prompt_tokens": 8000,
- "total_cost": "1000000000000000",
- "total_requests": 42,
- "total_tokens": 12345
}Get all API keys for current user
| status | string Filter: active / revoked / expired / all (default all) |
{- "data": [
- {
- "allowed_models": [
- "[\"glm-5\"]"
], - "allowed_providers": [
- "[\"0xabc...\"]"
], - "created_at": "2024-01-15T10:30:00Z",
- "credit_limit": "1.5",
- "expires_at": "2025-02-15T10:30:00Z",
- "key_id": "abc12345",
- "key_preview": "sk-abcde…",
- "name": "my-api-key",
- "reset_period": "monthly",
- "revoked": false,
- "status": "active",
- "trust_mode": "verified",
- "used": "0.42"
}
], - "object": "list"
}Create a new API key for LLM service access
API key configuration
| allowed_models | Array of strings AllowedModels is an optional allowlist of model IDs this key may invoke. Nil = no restriction. Empty slice = explicit empty list, rejected at validation (a key that can call no models is useless). |
| allowed_providers | Array of strings AllowedProviders is an optional allowlist of provider addresses (hex, 0x-prefixed) this key may target. Same nil-vs-empty convention as AllowedModels. |
| credit_limit | string 0G units; nil = unlimited |
| expiration | string RFC3339, "no_expiration", or "" |
| name | string |
| reset_period | string never/daily/weekly/monthly; "" → never |
| trust_mode | string TrustMode optionally pins this key to a single trust tier. Accepted values: "verified" | "private" | "" (no pin). The wire shape is a value type rather than a pointer because the create path has no "leave unchanged" semantics — absent / empty / explicit "" all mean "no pin". |
{- "allowed_models": [
- "string"
], - "allowed_providers": [
- "string"
], - "credit_limit": "string",
- "expiration": "string",
- "name": "string",
- "reset_period": "string",
- "trust_mode": "string"
}{- "allowed_models": [
- "[\"glm-5\"]"
], - "allowed_providers": [
- "[\"0xabc...\"]"
], - "created_at": "2024-01-15T10:30:00Z",
- "credit_limit": "1.5",
- "expires_at": "2025-02-15T10:30:00Z",
- "key": "string",
- "key_id": "abc12345",
- "key_preview": "sk-abcde…",
- "name": "my-api-key",
- "reset_period": "monthly",
- "revoked": false,
- "status": "active",
- "trust_mode": "verified",
- "used": "0.42"
}Update name / credit_limit / reset_period / expiration of an API key
| keyId required | string API Key ID |
Patch payload
| allowed_models | Array of strings AllowedModels / AllowedProviders sparse-PATCH sentinels: nil → unchanged non-nil empty [] → clear the allowlist (no restriction) non-nil non-empty → replace the allowlist Pointer to slice (rather than slice) so we can distinguish "leave alone" from "clear", matching how Scopes is handled on mgmt keys. |
| allowed_providers | Array of strings |
| credit_limit | string |
| expiration | string |
| name | string |
| reset_period | string |
| trust_mode | string TrustMode sparse-PATCH sentinels: nil → unchanged; "" → clear the pin (key falls back to no trust-mode restriction); any of verified|private → set the pin. |
{- "allowed_models": [
- "string"
], - "allowed_providers": [
- "string"
], - "credit_limit": "string",
- "expiration": "string",
- "name": "string",
- "reset_period": "string",
- "trust_mode": "string"
}{- "allowed_models": [
- "[\"glm-5\"]"
], - "allowed_providers": [
- "[\"0xabc...\"]"
], - "created_at": "2024-01-15T10:30:00Z",
- "credit_limit": "1.5",
- "expires_at": "2025-02-15T10:30:00Z",
- "key_id": "abc12345",
- "key_preview": "sk-abcde…",
- "name": "my-api-key",
- "reset_period": "monthly",
- "revoked": false,
- "status": "active",
- "trust_mode": "verified",
- "used": "0.42"
}Submit an image editing job to be processed asynchronously. The response includes jobId and provider_address — clients then poll /v1/async/jobs/{jobId} with ?provider_address=... to retrieve the result.
Supports provider routing preferences via X-0G-Provider-* request headers (Address, Sort, Trust-Mode, Allow-Fallbacks). Multipart endpoints have no body-side routing surface — headers only.
| X-0G-Provider-Address | string Routing: pin to a specific provider by on-chain address (0x-prefixed). |
| X-0G-Provider-Sort | string Routing: provider sort strategy. |
| X-0G-Provider-Trust-Mode | string Routing: trust tier filter ( |
| X-0G-Provider-Allow-Fallbacks | string Routing: whether to retry on other providers after a failure. |
{ }Submit an image generation job to be processed asynchronously. The response includes jobId and provider_address — clients then poll /v1/async/jobs/{jobId} with ?provider_address=... to retrieve the result.
Provider Routing: Use "provider": {...} body field OR X-0G-Provider-* request headers. Header > body precedence resolves same-field conflicts.
| X-0G-Provider-Address | string Routing: pin to a specific provider by on-chain address (0x-prefixed). |
| X-0G-Provider-Sort | string Routing: provider sort strategy. |
| X-0G-Provider-Trust-Mode | string Routing: trust tier filter ( |
| X-0G-Provider-Allow-Fallbacks | string Routing: whether to retry on other providers after a failure. |
Image generation request
| model | string Model ID |
| n | integer Number of images to generate |
| prompt | string Image description |
| response_format | string Response format: url or b64_json |
| size | string Image size |
{- "model": "dall-e-3",
- "n": 1,
- "prompt": "A beautiful sunset",
- "response_format": "url",
- "size": "1024x1024"
}{ }Transcribe audio file to text. Accepts either content type:
application/json (default, schema below): AudioTranscriptionRequest body with base64-encoded audio in file_base64.multipart/form-data (OpenAI-style): file part with audio bytes + model form field (plus optional language, response_format). Schema not auto-documented here — matches the OpenAI /v1/audio/transcriptions shape.
Supports provider routing preferences via X-0G-Provider-* request headers (Address, Sort, Trust-Mode, Allow-Fallbacks). Multipart requests have no body-side routing surface — headers only. JSON requests may also use the body provider: {...} field.| X-0G-Provider-Address | string Routing: pin to a specific provider by on-chain address (0x-prefixed). |
| X-0G-Provider-Sort | string Routing: provider sort strategy. |
| X-0G-Provider-Trust-Mode | string Routing: trust tier filter ( |
| X-0G-Provider-Allow-Fallbacks | string Routing: whether to retry on other providers after a failure. |
JSON-body shape (base64-encoded audio in file_base64). For multipart/form-data requests, send file + model form parts instead — see description.
| file_base64 | string Base64 encoded audio file |
| filename | string Filename |
| language | string Audio language |
| model | string Model ID |
| response_format | string Response format |
{- "file_base64": "SGVsbG8gd29ybGQ=",
- "filename": "audio.mp3",
- "language": "en",
- "model": "whisper-1",
- "response_format": "json"
}{- "duration": 5.5,
- "language": "en",
- "text": "Hello, world!"
}Send chat request to AI provider (OpenAI compatible API).
Web Search: Add "plugins": [{"id": "web"}] to enable real-time web search.
Search results are injected into the prompt context and returned as url_citation annotations
in the response. Works with any model. Multi-turn conversations automatically rewrite
the query for better search relevance. The injected search context tokens are billed
as normal input tokens.
File Attachments: Upload via POST /v1/files, then reference with
"attachments": [{"file_id": "file-..."}]. Extracted text is injected into the system prompt
and billed as normal input tokens.
Provider Routing: Use "provider": {"sort": "latency"|"price", "address": "0x...", "allow_fallbacks": true}
to influence provider selection. address overrides sort. The X-0G-Provider-* request headers (documented below) are the equivalent canonical surface.
| X-0G-Provider-Address | string Routing: pin to a specific provider by on-chain address (0x-prefixed). |
| X-0G-Provider-Sort | string Routing: provider sort strategy. |
| X-0G-Provider-Trust-Mode | string Routing: trust tier filter ( |
| X-0G-Provider-Allow-Fallbacks | string Routing: whether to retry on other providers after a failure. |
Chat request
Array of objects (github_com_0glabs_0g-router_pkg_inference.Attachment) File attachments (uploaded via /v1/files) | |
| max_tokens | integer Maximum output tokens |
Array of objects (github_com_0glabs_0g-router_pkg_inference.RequestMessage) Message list (content may be string or multimodal array) | |
| model | string Model ID |
Array of objects (github_com_0glabs_0g-router_pkg_inference.Plugin) Plugins to enable (e.g. [{"id":"web"}] for web search) | |
object Routing preferences (0G Router extension) | |
object Output format: json_object or json_schema for structured output | |
| stream | boolean Whether to stream output |
| temperature | number Temperature parameter (0-2) |
| tool_choice | any Which tool to use: "none", "auto", "required", or {"type":"function","function":{"name":"..."}} |
Array of objects (github_com_0glabs_0g-router_pkg_inference.Tool) Tools (functions) the model may call | |
| top_p | number Top-p sampling parameter |
{- "attachments": [
- {
- "file_id": "file-abc123"
}
], - "max_tokens": 1024,
- "messages": [
- {
- "content": "Hello!",
- "role": "user"
}
], - "model": "qwen/qwen-2.5-7b-instruct",
- "plugins": [
- {
- "id": "web"
}
], - "provider": {
- "address": "0x1234...",
- "allow_fallbacks": true,
- "sort": "latency",
- "trust_mode": "verified"
}, - "response_format": {
- "json_schema": null,
- "type": "json_schema"
}, - "stream": false,
- "temperature": 0.7,
- "tool_choice": null,
- "tools": [
- {
- "function": {
- "description": "Get weather",
- "name": "get_weather",
- "parameters": null
}, - "type": "function"
}
], - "top_p": 0.9
}{- "choices": [
- {
- "delta": {
- "content": "string",
- "reasoning": "string",
- "reasoning_content": "string",
- "role": "string"
}, - "finish_reason": "stop",
- "index": 0,
- "message": {
- "content": "Hello!",
- "role": "user"
}
}
], - "created": 1677652288,
- "id": "chatcmpl-123",
- "model": "qwen/qwen-2.5-7b-instruct",
- "object": "chat.completion",
- "usage": {
- "completion_tokens": 20,
- "prompt_tokens": 10,
- "prompt_tokens_details": {
- "cached_tokens": 0
}, - "total_tokens": 30
}, - "x_0g_trace": {
- "billing": {
- "input_cost": "0.00001",
- "output_cost": "0.00002",
- "total_cost": "0.00003"
}, - "provider": "0x1234...",
- "request_id": "req_abc123",
- "tee_verified": true
}
}Edit an image using AI (inpainting, variations).
Supports provider routing preferences via X-0G-Provider-* request headers (Address, Sort, Trust-Mode, Allow-Fallbacks). Multipart endpoints have no body-side routing surface — headers only.
| X-0G-Provider-Address | string Routing: pin to a specific provider by on-chain address (0x-prefixed). |
| X-0G-Provider-Sort | string Routing: provider sort strategy. |
| X-0G-Provider-Trust-Mode | string Routing: trust tier filter ( |
| X-0G-Provider-Allow-Fallbacks | string Routing: whether to retry on other providers after a failure. |
| image | string <binary> Source image file |
| prompt required | string Edit instruction |
| model required | string Model ID |
{- "created": 1677652288,
}Generate images using AI. Supports provider routing preferences (see /chat/completions).
| X-0G-Provider-Address | string Routing: pin to a specific provider by on-chain address (0x-prefixed). |
| X-0G-Provider-Sort | string Routing: provider sort strategy. |
| X-0G-Provider-Trust-Mode | string Routing: trust tier filter ( |
| X-0G-Provider-Allow-Fallbacks | string Routing: whether to retry on other providers after a failure. |
Image generation request
| model | string Model ID |
| n | integer Number of images to generate |
| prompt | string Image description |
| response_format | string Response format: url or b64_json |
| size | string Image size |
{- "model": "dall-e-3",
- "n": 1,
- "prompt": "A beautiful sunset",
- "response_format": "url",
- "size": "1024x1024"
}{- "created": 1677652288,
}Send chat request using Anthropic Messages API format.
Routes to providers that support the Anthropic format.
Supports web search plugins, file attachments, and provider routing preferences
(same as /chat/completions).
| X-0G-Provider-Address | string Routing: pin to a specific provider by on-chain address (0x-prefixed). |
| X-0G-Provider-Sort | string Routing: provider sort strategy. |
| X-0G-Provider-Trust-Mode | string Routing: trust tier filter ( |
| X-0G-Provider-Allow-Fallbacks | string Routing: whether to retry on other providers after a failure. |
Anthropic Messages request
Array of objects (github_com_0glabs_0g-router_pkg_inference.Attachment) | |
| max_tokens | integer |
| messages | Array of any AnthropicMessage objects |
| metadata | any |
| model | string |
Array of objects (github_com_0glabs_0g-router_pkg_inference.Plugin) 0G Router extensions (stripped before forwarding) | |
object (github_com_0glabs_0g-router_pkg_inference.ProviderPreferences) | |
| stop_sequences | Array of strings |
| stream | boolean |
| system | any string or []AnthropicContentBlock |
| temperature | number |
| tool_choice | any |
| tools | Array of any |
| top_k | integer |
| top_p | number |
{- "attachments": [
- {
- "file_id": "file-abc123"
}
], - "max_tokens": 0,
- "messages": [
- null
], - "metadata": null,
- "model": "string",
- "plugins": [
- {
- "id": "web"
}
], - "provider": {
- "address": "0x1234...",
- "allow_fallbacks": true,
- "sort": "latency",
- "trust_mode": "verified"
}, - "stop_sequences": [
- "string"
], - "stream": true,
- "system": null,
- "temperature": 0,
- "tool_choice": null,
- "tools": [
- null
], - "top_k": 0,
- "top_p": 0
}{- "content": [
- {
- "id": "string",
- "input": null,
- "name": "string",
- "text": "string",
- "type": "string"
}
], - "id": "string",
- "model": "string",
- "role": "string",
- "stop_reason": "string",
- "type": "string",
- "usage": {
- "cache_creation_input_tokens": 0,
- "cache_read_input_tokens": 0,
- "input_tokens": 0,
- "output_tokens": 0
}
}Get all available AI models — the canonical view: one row per canonical_id, with curated registry metadata and endpoints aggregated (max context, union of params/formats, cheapest pricing); id is the canonical model id. To enumerate the endpoints behind a canonical id, call GET /v1/providers?canonical_id=<id>. provider_address uses OR (match any), input_modality and supported_parameter use AND (must match all).
| provider_address | Array of strings Filter by provider address (OR: match any) |
| input_modality | Array of strings Filter by input modality, e.g. text, image (AND: must support all) |
| supported_parameter | Array of strings Filter by supported parameter, e.g. temperature (AND: must support all) |
{- "data": [
- {
- "architecture": {
- "input_modalities": [
- "string"
], - "instruct_type": "string",
- "modality": "string",
- "output_modalities": [
- "string"
], - "tokenizer": "string"
}, - "context_length": 0,
- "created": 1737936000,
- "default_parameters": {
- "property1": null,
- "property2": null
}, - "description": "string",
- "expiration_date": "string",
- "id": "qwen-2.5-7b-instruct",
- "max_completion_tokens": 0,
- "name": "string",
- "object": "model",
- "owned_by": "0G Foundation",
- "pricing": {
- "cached_prompt": "string",
- "completion": "string",
- "image": "string",
- "prompt": "string",
- "tiered_pricing": [
- {
- "cached_prompt": "string",
- "completion": "string",
- "max_input_tokens": 0,
- "prompt": "string"
}
]
}, - "pricing_usd": {
- "cached_prompt": "string",
- "completion": "string",
- "image": "string",
- "prompt": "string",
- "tiered_pricing": [
- {
- "cached_prompt": "string",
- "completion": "string",
- "max_input_tokens": 0,
- "prompt": "string"
}
]
}, - "provider_count": 0,
- "supported_formats": [
- "string"
], - "supported_parameters": [
- "string"
], - "tee_attested": true,
- "tee_type": "string",
- "tee_verifier": "string",
- "type": "string",
- "verifiability": "string"
}
], - "object": "list"
}Get all TEE-acknowledged providers, optionally narrowed by service type, on-chain model id, and/or canonical id. model and canonical_id are independent filters and compose (ANDed): canonical_id alone lists every endpoint of a canonical, while model + canonical_id narrows to a specific endpoint within it. An empty value means "not filtered on" (so no filters = list all). Includes providers with unknown health status (is_healthy=null).
| service_type | string Filter by service type (chatbot, text-to-image, speech-to-text) |
| model | string Filter by on-chain model ID (e.g. zai-org/GLM-5.1-FP8); exact model_id match. Empty = not filtered. |
| canonical_id | string [beta] Filter by canonical model ID (e.g. glm-5.1); lists every endpoint serving that canonical. Composes (AND) with model. Empty = not filtered. |
{- "data": [
- {
- "address": "0x1234567890abcdef",
- "architecture": {
- "input_modalities": [
- "string"
], - "instruct_type": "string",
- "modality": "string",
- "output_modalities": [
- "string"
], - "tokenizer": "string"
}, - "canonical_id": "glm-5.1",
- "context_length": 0,
- "default_parameters": {
- "property1": null,
- "property2": null
}, - "is_healthy": true,
- "latency": 150,
- "max_completion_tokens": 0,
- "model_id": "qwen-2.5-7b-instruct",
- "name": "string",
- "pricing": {
- "cached_prompt": "string",
- "completion": "string",
- "image": "string",
- "prompt": "string",
- "tiered_pricing": [
- {
- "cached_prompt": "string",
- "completion": "string",
- "max_input_tokens": 0,
- "prompt": "string"
}
]
}, - "pricing_usd": {
- "cached_prompt": "string",
- "completion": "string",
- "image": "string",
- "prompt": "string",
- "tiered_pricing": [
- {
- "cached_prompt": "string",
- "completion": "string",
- "max_input_tokens": 0,
- "prompt": "string"
}
]
}, - "service_type": "chatbot",
- "supported_formats": [
- "string"
], - "supported_parameters": [
- "string"
], - "tee_acknowledged": true,
- "tee_attested": true,
- "tee_type": "string",
- "tee_verifier": "string",
- "type": "string",
- "uptime": 99.5,
- "verifiability": "string"
}
], - "object": "list"
}