Sandbox
Build and test your integration for free with test keys; runs are simulated and nothing is charged.
The sandbox is a separate copy of the API for building and testing. It takes the same requests, validates them the same way and answers with the same response shapes, but it never runs a model and never spends credits.
| Live | Sandbox | |
|---|---|---|
| Base URL | https://api-live.aitopia.ai | https://api-sandbox.aitopia.ai |
| Key | aitk_live_... | aitk_test_... |
| Runs | Real models, real files | Simulated, sample files |
| Credits | Charged | Never charged |
| Input validation and price estimate | Yes | Yes, the same |
#Test keys
Create a test key under profile menu > API keys on aitopia.ai, next to your live keys. Test keys count toward the same limit of 10 active keys, have their own webhook secret and can be revoked the same way.
A key works only on its own server. A test key sent to the live server, or a live key sent to the sandbox, is refused, so a test setup can never spend credits by accident:
{
"error": {
"code": "KEY_ENVIRONMENT_MISMATCH",
"message": "This is a sandbox (test) key. Send it to https://api-sandbox.aitopia.ai, or use a live key here.",
"retryable": false
}
}Switching an integration from sandbox to live means changing two values: the base URL and the key.
export AITOPIA_BASE="https://api-sandbox.aitopia.ai"
export AITOPIA_KEY="aitk_test_..."#What is real and what is simulated
The same as live:
GET /v1/modelsandGET /v1/models/{model_id}: the real catalogue, input schemas and prices.- Validation: a request the live API would refuse (unknown model, missing or invalid field) is refused in the sandbox with the same error.
?dry_run=true: the real price estimate.credits_availableis the sandbox balance.- File uploads (
POST /v1/uploads,POST /v1/uploads/link): real and free, so you can test your upload code end to end. - Rate limits, webhook signatures and retries,
?wait, cancel, error format.
Simulated:
- Submits (
POST /v1/models/{model_id},POST /v1/edit,POST /v1/batch) answer202with arequest_idas usual, but no model runs. The request isqueuedfor about a second, thenrunning, then finishes after a few seconds (images about 4 s, audio about 5 s, video about 8 s). - A completed request returns a sample file of the right kind: an image, a video or an audio clip.
credits_estimatedholds the real estimate; nothing is charged. POST /v1/editis not planned in the sandbox (noplan_tokenis needed or produced) and finishes like a run.GET /v1/account/balancereturns a fixed play balance of10000credits with"sandbox": true.
Sandbox requests and live requests are kept apart: a test key cannot read or cancel a live request, and a live key cannot see a sandbox one.
#Testing failures
Send X-Sandbox-Outcome on a sandbox submit to choose how the simulated run ends:
| Value | Result |
|---|---|
completed (default) | The request completes with a sample file. |
failed | The request fails with UPSTREAM_RUN_FAILED and retryable: true, as a provider failure would. |
partial | For POST /v1/batch: the first item fails, the others complete, and the request ends partial. A single run fails. |
The header is ignored on the live server.
curl -X POST "https://api-sandbox.aitopia.ai/v1/models/google/nano-banana-2?wait=10" \
-H "Authorization: Key $AITOPIA_KEY" \
-H "Content-Type: application/json" \
-H "X-Sandbox-Outcome: failed" \
-d '{"prompt": "a red bicycle"}'const res = await fetch("https://api-sandbox.aitopia.ai/v1/models/google/nano-banana-2?wait=10", {
method: "POST",
headers: {
Authorization: `Key ${process.env.AITOPIA_KEY}`,
"Content-Type": "application/json",
"X-Sandbox-Outcome": "failed",
},
body: JSON.stringify({ prompt: "a red bicycle" }),
});
const request = await res.json();
console.log(request.status, request.error);import os, requests
r = requests.post(
"https://api-sandbox.aitopia.ai/v1/models/google/nano-banana-2",
params={"wait": 10},
headers={
"Authorization": f"Key {os.environ['AITOPIA_KEY']}",
"X-Sandbox-Outcome": "failed",
},
json={"prompt": "a red bicycle"},
)
print(r.json()["status"], r.json().get("error"))#Webhooks in the sandbox
A sandbox submit with webhook_url gets its webhook like a live one: signed with the test key's webhook secret, retried on failure, with sandbox URLs in status_url, result_url and cancel_url. Use it to test your receiver and signature check before going live.
#Going live
- Create a live key under profile menu > API keys.
- Replace the base URL with
https://api-live.aitopia.aiand the key with the live key. - Make sure the account has credits (Billing & retention).
Nothing else changes: request and response shapes are the same.