API docsGet started

Sandbox

The sandbox is a free copy of the API for integration testing. It takes the same requests and returns the same response and error formats as the live API, but answers with sample results: no model is called, no credits are charged and nothing is stored. Develop against the sandbox base URL, then switch to the live one for production.

Live base URL

https://01router.com/api/v1

Sandbox base URL

https://01router.com/api/sandbox/v1

Supported endpoints

POST/chat/completionsSupported

OpenAI-compatible chat. Returns a fixed reply at once; with "stream": true it sends SSE chunks, a usage chunk and [DONE].

POST/generationsSupported

Checks that the model exists, then returns a generation in processing status with an id starting with sbx_. Nothing is charged.

GET/generations/{id}Supported

processing for about 3 seconds after creation, then succeeded with a real sample from the prompt library: an image, video or audio file of the same model when it has one, else of the same type.

POST/generations/{id}/cancelSupported

Cancels while the generation is processing (status failed, error "Canceled by user"); once it succeeded, returns 409 not_cancelable.

GET/generationsSupported

Always an empty list, because sandbox generations are not stored.

POST/images/generationsSupported

OpenAI-compatible image generation. Returns n sample images from the prompt library at once, as url or as b64_json.

GET/models · /models/{slug}Supported

Free to read, so it redirects (307) to the live model catalog and returns real data.

POST/quoteUse the live API

Not in the sandbox. Quotes are free: call the live endpoint directly.

GET/prompts · /prompts/{id}Use the live API

Not in the sandbox. The prompt library is free: call the live endpoint directly.

Request

OpenAI SDK · switch the base URL
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.API_KEY,
  // Live: https://01router.com/api/v1
  baseURL: 'https://01router.com/api/sandbox/v1',
});

const reply = await client.chat.completions.create({
  model: 'gpt-6-sol',
  messages: [{ role: 'user', content: 'Hello!' }],
});
cURL · create a generation
curl 'https://01router.com/api/sandbox/v1/generations' \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "seedance-2.5",
  "input": {
    "prompt": "A red fox running through fresh snow, cinematic"
  }
}'
cURL · poll the generation
curl 'https://01router.com/api/sandbox/v1/generations/sbx_example' \
  -H "Authorization: Bearer $API_KEY"
cURL · simulate an error
curl 'https://01router.com/api/sandbox/v1/generations' \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Sandbox-Error: 402" \
  -d '{"model":"seedance-2.5","input":{"prompt":"A red fox running through fresh snow, cinematic"}}'

Response example

200 · application/json
{
  "id": "sbx_example",
  "object": "generation",
  "model": "seedance-2.5",
  "type": "video",
  "provider": "sandbox",
  "status": "processing",
  "input": {
    "prompt": "A red fox running through fresh snow, cinematic"
  },
  "outputs": [],
  "error": null,
  "credits": 0,
  "price_usd": 0,
  "created_at": "2026-10-25T08:00:00.000Z",
  "completed_at": null
}
200 · polled again after about 3 seconds
{
  "id": "sbx_example",
  "object": "generation",
  "model": "seedance-2.5",
  "type": "video",
  "provider": "sandbox",
  "status": "succeeded",
  "input": {},
  "outputs": [
    "https://example.com/sandbox.mp4"
  ],
  "error": null,
  "credits": 0,
  "price_usd": 0,
  "created_at": "2026-10-25T08:00:00.000Z",
  "completed_at": "2026-10-25T08:00:03.000Z"
}
402 · X-Sandbox-Error: 402
{
  "error": {
    "message": "Sandbox simulated 402 error",
    "code": "insufficient_credits"
  }
}

Responses are illustrative. IDs, usage, prices and results depend on the actual request.

Usage notes

  • Going live only changes the base URL back to https://01router.com/api/v1. Request bodies, response fields and error formats stay the same, so no other code changes are needed. From then on every request calls the model and is charged.
  • Send your normal API key as Authorization: Bearer sk_…. The sandbox checks only the key's format and never looks it up, so project restrictions, IP allow-lists and key quotas do not apply.
  • Generations stay processing for about 3 seconds and then succeed, so your polling loop runs as in production. Outputs are real files from the prompt library, picked by model (else by type); the same generation always returns the same output.
  • Chat always replies with the same sentence. usage.prompt_tokens is estimated from your messages and completion_tokens from the reply; json_object and json_schema requests get a small JSON object back.
  • To test error handling, add the X-Sandbox-Error header with 400, 401, 402, 404, 429, 500, 502 or 503. Every supported endpoint then returns that status with the same error body as the live API (error.message and error.code).
  • Sandbox generation ids start with sbx_ and work only on the sandbox; live ids don't work on the sandbox either.
  • Not simulated: per-model parameter checks, provider routing, projects and custom models, key quotas, callback_url and pricing (credits and price_usd are always 0). Sandbox requests don't appear in your task log or usage, and are rate-limited to about 10 per second per IP.

Use with AI

Give your coding assistant the documentation index or the full API reference, including live model parameters.