T0 API documentation

Hosted, sandboxed agent sessions over HTTP. Create a session, push files into it, send it messages, and stream the agent working — in an isolated Linux workspace that is still there on the next message.

Base URL
https://api.t0.sikasio.com/v1
Auth
Authorization: Bearer t0k_live_YOUR_KEY
Streaming
Server-Sent Events, resumable via Last-Event-ID, plus a bidirectional WebSocket
Models
core · max — you bring your own provider key
Free plan
300 credits/month (5 h of awake session time), no card required
Status
status.t0.sikasio.com

A session is an isolated sandbox, a persistent workspace and one long-lived agent process. A turn is one message in and one response out, streamed as ordered, sequence-numbered events. Files written by the agent, packages it installed and git state all survive between messages, so message two builds on message one.

T0 sells the runtime, not the model. Isolation, persistence, orchestration and latency are the product; each account supplies its own model provider key, so no token is resold and nothing on your bill is a marked-up token.

Get your free API key →

Getting your API key

  1. Create an account at /signup — email and password, no card.
  2. Verify your email with the code we send you.
  3. Copy your API key. It is shown once, right after verification. Store it somewhere safe; you can always issue a fresh one from the dashboard.
  4. Add your model provider key in the dashboard. T0 is bring-your-own-key: the agent runs against your provider account, and your key is encrypted at rest and injected into the sandbox only at the moment a container is claimed.
  5. Make your first call — see the quickstart below.

Already have an account? Sign in. Want to try the API without writing a client first? The playground is built on nothing but the public API and your own key.

Authentication

Every /v1 request carries your key as a bearer token:

Authorization: Bearer t0k_live_YOUR_KEY

The key is the tenant boundary: it identifies the account, authorizes the request, and is what usage is metered against. Every session, event and file belongs to the account behind the key, and a request for another account’s session is a 404, never a redirect or a hint.

Keys are stored as an indexed prefix plus an HMAC-SHA256 digest — never in plaintext — and compared in constant time. Revoking a key from the dashboard takes effect within seconds, everywhere.

Keep keys server-side. The API host sets no cookies and is a separate origin from this portal, so there is no session to borrow and no CSRF surface — but a key shipped in a browser bundle is a key you have given away. Call T0 from a server you control, or proxy it.

A missing, malformed, revoked or unknown key returns 401 invalid_key. A valid key used against another account’s resource returns 403 forbidden.

Plans & quotas

A credit is one minute of awake session time. Sleeping sessions cost nothing, so a session you leave open overnight and wake in the morning is billed for the minutes it worked, not the hours it waited.

 FreeStarterPro
Price$0$19/mo$59/mo
Credits / monthone credit = one minute awake300 (5 h)3,600 (60 h)18,000 (300 h)
Daily capcredits per UTC day606002,400
Concurrent sessions1310
Workspace storagedurable, per account2 GB25 GB100 GB
Live disk per sessiontechnical ceiling5 GB10 GB20 GB
Retentionafter a session ends7 days30 days90 days
Sandboxmemory / CPU1 GB / 1 CPU2 GB / 1.5 CPU4 GB / 2 CPU

Metered: awake session-seconds, peak workspace bytes and turns. Token counts are recorded and shown to you for your own visibility — under bring-your-own-key they are not billed by T0. Enforced: concurrent sessions, monthly and daily credits, workspace size, retention window and request rate.

Overage is a hard stop, never a surprise bill. When a quota is reached the API returns 429 quota_exceeded naming the limit and the next plan up. Sessions already running are not killed mid-turn.

Full breakdown on the pricing page. Live figures for your own account come from GET /v1/usage.

Quickstart

Create a session, put a file in it, send a message, and read the result back out. Session creation is a claim against a pool of pre-booted containers, so it is bookkeeping rather than a boot.

From zero to a finished turn
# 1. create a session — comes from the warm pool, ready in well under a second
SESSION=$(curl -s -X POST https://api.t0.sikasio.com/v1/sessions \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"quickstart","model":"core"}' | jq -r .id)

# 2. push a file into its workspace
curl -X PUT https://api.t0.sikasio.com/v1/sessions/$SESSION/files/notes.md \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  --data-binary @notes.md

# 3. stream the events, then send a message from another shell
curl -N https://api.t0.sikasio.com/v1/sessions/$SESSION/events \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Accept: text/event-stream" &

curl -X POST https://api.t0.sikasio.com/v1/sessions/$SESSION/messages \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"Summarise notes.md into summary.md, then run the tests."}'

# 4. take the result back out — works even after the session has gone to sleep
curl -s https://api.t0.sikasio.com/v1/sessions/$SESSION/files/summary.md \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -o summary.md

Sessions

A session owns a container, a workspace volume and a live agent process. The process stays alive for the life of the session, which is what keeps follow-up turns fast.

States

StateMeaning
readyAwake and idle. Send it a message.
workingA turn is in flight; events are streaming.
sleepingIdle past idle_timeout: the container is stopped, the workspace is kept, and nothing is being metered. The next message wakes it.
expiredPast its ttl or its plan’s retention window. The workspace has been deleted.
failedThe sandbox could not be started or the agent died unrecoverably.

Create a session

POST/v1/sessionsrequires API key
FieldTypeDefaultNotes
namestringYour own label, returned on every read. Purely for your bookkeeping.
modelstringcorecore for everyday work, max for the hardest tasks. Fixed for the life of the session.
idle_timeoutinteger (s)600Seconds of inactivity before the session sleeps. Sleeping is free, so a short timeout costs you nothing but a resume.
ttlinteger (s)plan retentionHard lifetime. At expiry the workspace is deleted, whatever state the session is in.
envobjectEnvironment variables for the workspace. Do not put your provider key here — T0 injects that for you.
Create a session
curl -X POST https://api.t0.sikasio.com/v1/sessions \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "invoice-parser",
    "model": "core",
    "idle_timeout": 600,
    "ttl": 86400,
    "env": { "NODE_ENV": "test" }
  }'

Response — 201

{
  "id": "sess_7f3a9c2e",
  "name": "invoice-parser",
  "state": "ready",
  "model": "core",
  "stream_url": "https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/events",
  "idle_timeout": 600,
  "created_at": "2026-08-17T09:14:02.117Z",
  "last_active_at": "2026-08-17T09:14:02.117Z",
  "expires_at": "2026-08-18T09:14:02.117Z"
}

List sessions

GET/v1/sessions?limit&cursorrequires API key

Cursor-paginated, newest first. limit defaults to 20; follow next_cursor until it comes back null.

List sessions
curl -s "https://api.t0.sikasio.com/v1/sessions?limit=20" -H "Authorization: Bearer t0k_live_YOUR_KEY"

# next page
curl -s "https://api.t0.sikasio.com/v1/sessions?limit=20&cursor=c_9f21b0" -H "Authorization: Bearer t0k_live_YOUR_KEY"
Response — 200
{
  "data": [
    { "id": "sess_7f3a9c2e", "name": "invoice-parser", "state": "working",  "workspace_bytes": 41235968 },
    { "id": "sess_2b8d41af", "name": "nightly-refactor", "state": "sleeping", "workspace_bytes": 8912384 }
  ],
  "next_cursor": "c_9f21b0"
}

Retrieve a session

GET/v1/sessions/:idrequires API key

Reading a sleeping session does not wake it — this is the cheap way to poll state and workspace size.

Retrieve a session
curl -s https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e -H "Authorization: Bearer t0k_live_YOUR_KEY"

Delete a session

DELETE/v1/sessions/:idrequires API key

Stops the container and deletes the workspace immediately, including its snapshot. Returns 204. Download anything you want to keep first — this is not reversible.

Delete a session
curl -X DELETE https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e -H "Authorization: Bearer t0k_live_YOUR_KEY"

Interrupt a turn

POST/v1/sessions/:id/interruptrequires API key

Stops the turn in flight without killing the session: the agent process stays alive, the workspace keeps whatever was written, and the session returns to ready. Interrupting an idle session is a no-op.

Interrupt
curl -X POST https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/interrupt -H "Authorization: Bearer t0k_live_YOUR_KEY"

Messages & streaming

Sending a message is fire-and-forget: it returns 202 with a turn_id as soon as the prompt is written into the running agent. All output arrives on the event stream, so a slow turn never holds an HTTP request open.

Send a message

POST/v1/sessions/:id/messagesrequires API key
FieldTypeDefaultNotes
contentrequiredstringThe message for the agent.
streambooleantrueEmit text.delta events as the response is produced. With false you still get turn.completed, just no token-by-token output.
Send a message
curl -X POST https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/messages \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Add a failing test for the invoice date parser, then make it pass.",
    "stream": true
  }'
Response — 202
{ "turn_id": "turn_04c7", "session_id": "sess_7f3a9c2e", "state": "working" }

A session that is sleeping wakes on the message. A message sent while a turn is already running returns 409 session_not_ready — interrupt first, or wait for turn.completed.

Event stream (SSE)

GET/v1/sessions/:id/eventsrequires API key

Server-Sent Events, one ordered and sequence-numbered stream per session. The id of each frame is that sequence number.

On the wire
id: 126
event: turn.started
data: {"turn_id":"turn_04c7","seq":126}

id: 127
event: text.delta
data: {"turn_id":"turn_04c7","seq":127,"text":"Reading src/parser.ts"}

id: 128
event: tool.started
data: {"turn_id":"turn_04c7","seq":128,"tool":"shell","summary":"npm test"}

id: 129
event: tool.output
data: {"turn_id":"turn_04c7","seq":129,"tool":"shell","chunk":"2 passing\n"}

id: 130
event: file.changed
data: {"seq":130,"path":"src/parser.ts","change":"modified","bytes":4192}

id: 131
event: turn.completed
data: {"turn_id":"turn_04c7","seq":131,"usage":{"session_seconds":38,"tokens_in":12480,"tokens_out":842,"cache_read":11200,"cache_write":1280}}
EventCarries
session.readyThe sandbox is claimed and the agent process is up.
turn.startedturn_id — a message has been accepted and work has begun.
text.deltaA fragment of the agent’s response, unbuffered.
tool.startedThe tool the agent reached for, and a one-line summary.
tool.outputA chunk of that tool’s output — shell stdout, test results.
file.changedA workspace path that was created, modified or deleted, with its new size.
turn.completedThe turn is done, and carries the usage it cost: session seconds, tokens in and out, cache reads and writes.
session.idleThe session has slept. Metering stops here; the workspace is kept.
session.expiredThe workspace has been deleted. The stream ends.
errorSomething went wrong inside the session, in the same { code, message } shape as an HTTP error.

Resuming a dropped stream

Reconnect with a Last-Event-ID header carrying the last sequence number you processed and the stream continues from the next event — nothing lost, nothing replayed twice. This is the standard SSE reconnect header, so a browser EventSource does it for you; a hand-rolled client should track the id itself, as below. Events are retained for a replay window generous enough to cover a reconnect, not as a permanent log — for a long turn, keep your own copy.

Stream and resume
# -N disables curl's own buffering so deltas appear as they are produced
curl -N https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/events \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Accept: text/event-stream"

# reconnecting after a drop: resume from the last id you saw, nothing is lost
curl -N https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/events \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Accept: text/event-stream" \
  -H "Last-Event-ID: 128"

WebSocket

WS/v1/sessions/:id/socketrequires API key

The same events, plus the ability to push. Send { "type": "message", "content": "…" } to start a turn and { "type": "interrupt" } to stop one, on the same connection the events arrive on. Use it when you want one connection instead of two; use SSE when you want the simplest possible client and free reconnection.

Bidirectional socket
# curl 8 speaks WebSocket; --no-buffer keeps frames unbuffered
curl --include --no-buffer \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: c2FtcGxlLWtleS0xMjM0NTY=" \
  https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/socket

Files

Files move in and out at any time — before a message, during a turn, or long after the session has gone to sleep. Every path is resolved and confined to /workspace before it reaches the container; anything that escapes it is rejected with 400 invalid_path without ever being touched by the sandbox.

Two transfer paths, chosen by size. Files under 10 MB stream straight through the API into the live workspace — one hop, lowest latency. Larger or bulk transfers are handed a presigned object-storage URL so the bytes never pass through our servers, which is why the upload ceiling is generous.

Upload a file

PUT/v1/sessions/:id/files/*pathrequires API key

Raw body, no multipart wrapper. Creates parent directories as needed and overwrites silently. Returns 201 with the stored path and byte count.

Upload one file
curl -X PUT https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/files/src/parser.ts \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @src/parser.ts

Bulk upload

POST/v1/sessions/:id/filesrequires API key

A tar.gz body, unpacked into /workspace. Every entry in the archive is path-checked the same way a single upload is, and an archive containing one bad entry is rejected whole. This is the right way to seed a repository into a fresh session.

Upload a tree
# whole trees go up as one tar.gz — one request instead of a thousand
tar czf - src package.json | curl -X POST https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/files \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -H "Content-Type: application/gzip" \
  --data-binary @-

Download a file

GET/v1/sessions/:id/files/*pathrequires API key

The raw bytes, with the content type inferred from the extension. This works on a sleeping session too, served straight from the workspace snapshot — you never have to pay to wake a session just to fetch its results.

Download a file
# works while the session is asleep — served from the snapshot, no wake needed
curl -s https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/files/dist/report.pdf \
  -H "Authorization: Bearer t0k_live_YOUR_KEY" \
  -o report.pdf

List files

GET/v1/sessions/:id/files?path&recursiverequires API key
List the workspace
curl -s "https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/files?path=/&recursive=true" -H "Authorization: Bearer t0k_live_YOUR_KEY"
Response — 200
{
  "path": "/",
  "files": [
    { "path": "package.json",   "bytes": 412,   "modified_at": "2026-08-17T09:15:44.002Z" },
    { "path": "src/parser.ts",  "bytes": 4192,  "modified_at": "2026-08-17T09:18:10.551Z" },
    { "path": "dist/report.pdf","bytes": 208133,"modified_at": "2026-08-17T09:19:02.884Z" }
  ],
  "workspace_bytes": 41235968
}

Delete a file

DELETE/v1/sessions/:id/files/*pathrequires API key

Removes a file or, for a directory path, the tree beneath it. Returns 204.

Delete a file
curl -X DELETE https://api.t0.sikasio.com/v1/sessions/sess_7f3a9c2e/files/tmp/scratch.log -H "Authorization: Bearer t0k_live_YOUR_KEY"

Account & health

Who am I

GET/v1/merequires API key

The account behind the key, its plan and limits, and whether a provider key is configured. The provider key itself is never returned — by any endpoint, ever.

Read the account
curl -s https://api.t0.sikasio.com/v1/me -H "Authorization: Bearer t0k_live_YOUR_KEY"
Response — 200
{
  "account_id": "acct_51f0",
  "email": "you@example.com",
  "plan": "starter",
  "key": { "prefix": "t0_live_9f21", "name": "server", "last_used_at": "2026-08-17T09:14:02.117Z" },
  "limits": {
    "concurrent_sessions": 3,
    "credits_per_month": 3600,
    "credits_per_day": 600,
    "storage_bytes": 26843545600,
    "retention_days": 30
  },
  "provider_key": { "configured": true, "updated_at": "2026-08-02T11:03:19.000Z" }
}

Usage

GET/v1/usage?from&torequires API key

Credits used and remaining, awake session seconds, turns, peak storage and token counts, with a daily breakdown. from and to are inclusive dates; the default window is the current billing month.

Read usage
curl -s "https://api.t0.sikasio.com/v1/usage?from=2026-08-01&to=2026-08-17" -H "Authorization: Bearer t0k_live_YOUR_KEY"
Response — 200
{
  "from": "2026-08-01",
  "to": "2026-08-17",
  "credits_included": 3600,
  "credits_used": 812,
  "credits_remaining": 2788,
  "session_seconds": 48702,
  "turns": 1394,
  "storage_bytes_peak": 5033164800,
  "tokens": { "in": 8114203, "out": 402118, "cache_read": 7411002, "cache_write": 703201 },
  "daily": [
    { "day": "2026-08-16", "session_seconds": 3120, "turns": 88, "credits": 52 },
    { "day": "2026-08-17", "session_seconds": 1980, "turns": 41, "credits": 33 }
  ]
}

Health

GET/healthpublic — no key

Liveness only. Cheap enough to poll from a load balancer.

Liveness
curl -s https://api.t0.sikasio.com/health

Status

GET/statuspublic — no key

Public component health — this is what the status page polls. It lives on its own host so it survives an outage of the stack it reports on.

Component health
curl -s https://api.t0.sikasio.com/status
Response — 200
{
  "components": [
    { "name": "gateway", "status": "operational", "p95_ms": 24 },
    { "name": "runner",  "status": "operational", "pool_depth": 12, "queue_depth": 0 },
    { "name": "storage", "status": "operational" }
  ],
  "error_rate_5m": 0.0009,
  "updated_at": "2026-08-17T09:20:00.000Z"
}

Parameters at a glance

Base URLhttps://api.t0.sikasio.com/v1
Auth headerAuthorization: Bearer t0k_live_YOUR_KEY
Modelscore (default) · max
Session statesready · working · sleeping · expired · failed
Eventssession.ready · turn.started · text.delta · tool.started · tool.output · file.changed · turn.completed · session.idle · session.expired · error
idle_timeoutSeconds; default 600. Sleeping is never metered.
ttlSeconds; defaults to the plan retention window (Free 7 d · Starter 30 d · Pro 90 d).
Direct uploadUp to 10 MB per request; larger transfers get a presigned URL.
Workspace root/workspace — every path is confined to it.
Stream resumeLast-Event-ID: <seq> on the SSE endpoint.
CreditOne minute of awake session time.

Errors

One shape, everywhere — including the error event on a stream. Codes are stable and machine-readable; messages are for humans and should never be parsed. The request_id is what support needs to find your request in the logs.

{
  "error": {
    "code": "quota_exceeded",
    "message": "Daily credit cap reached for plan starter. Upgrade to pro for 2,400 credits per day.",
    "request_id": "req_0c41a7d9"
  }
}
StatusCodeMeaning
400invalid_pathA file path escaped /workspace, or was otherwise unusable. Rejected before it reached the container.
401invalid_keyMissing, malformed, unknown or revoked API key.
403forbiddenA valid key for the wrong account, or an action your plan does not allow.
404not_foundUnknown session, file or route — and what another account’s session looks like.
409session_not_readyThe session is busy with a turn, waking, or in a state that cannot accept the request yet.
412provider_key_requiredThe account has no provider key on file, so a session cannot be created. Add one in the dashboard; sessions run on your own key.
413payload_too_largeThe body is over the direct-upload ceiling, or the workspace would exceed your plan’s size limit.
429rate_limitedPer-key request rate exceeded. Retry after the Retry-After header.
429quota_exceededA plan quota is exhausted — credits, concurrent sessions or storage. The message names the limit and the next plan up.
500internalOur fault. The message is deliberately generic; quote the request_id and we can find it.
503unavailableA dependency is briefly down. Nothing is broken on your side — retry with backoff.

Rate limits

Each key has a token bucket: short bursts are fine, sustained flooding is not. Exceeding it returns 429 rate_limited with a Retry-After header in seconds. Rate limits and quotas are both enforced at the front of the gateway, before any work is done — a rejected request never claims a container and never spends a credit.

Rate limiting is per key, so issuing a separate key per service keeps a runaway job from starving the rest of your account. Quotas, by contrast, are per account: concurrent sessions, credits, storage and retention are shared across every key you hold.

LimitScopeOn exceeding
Request ratePer key429 rate_limited + Retry-After
Concurrent sessionsPer account429 quota_exceeded on session create
Daily and monthly creditsPer account429 quota_exceeded; running turns finish
Workspace storagePer account413 payload_too_large on the write that would cross it

FAQ

What is T0?

T0 sells hosted, sandboxed AI coding-agent sessions over a REST API. You create a session, push files into it, send it messages, and stream the agent working in real time. Each session is an isolated Linux workspace that persists between messages, so files the agent wrote, packages it installed and git state are all still there on the next message.

T0 sells the runtime, not the model: isolation, persistence, orchestration and latency are the product. Base URL: https://api.t0.sikasio.com/v1.

How do I get an API key?

Create an account at https://t0.sikasio.com/signup with an email and a password, verify the code we email you, and your key is shown once — copy it straight away. Send it as an Authorization: Bearer header on every /v1 request.

Keys are the tenant boundary: they identify the account, authorize the request, and are what usage is metered against. Revoke one from the dashboard and it stops working within seconds.

Do I need my own model provider key?

Yes. T0 is bring-your-own-key: you add your model provider key once in the dashboard and T0 runs the agent with it. We do not resell model tokens, so nothing on your bill is a marked-up token — you pay us for compute time and storage only.

Your provider key is encrypted at rest with AES-256-GCM, decrypted only at the moment a container is claimed, injected as an environment variable inside your sandbox, and never logged, never written to disk and never returned by any endpoint.

Which models can I use?

Two tiers, named by T0: core for everyday work and max for the hardest tasks. Set the tier when you create a session; core is the default. Because you bring your own key, the tier selects the class of model your key is used against.

What persists between messages?

Everything inside /workspace, plus the agent process itself. The process stays alive for the life of the session, so conversation context stays resident and follow-up turns do not re-read everything from scratch. That is the single largest latency win in the system.

When a session goes idle the container stops but its volume survives, so resuming is a start rather than a rebuild. Workspaces are also snapshotted to object storage, which is what makes a resume possible days later.

What happens when a session goes idle?

After idle_timeout (10 minutes by default) the session moves to sleeping: the container stops, the workspace is kept, and a session.idle event is emitted. Sleeping costs nothing — metering counts awake seconds only.

The next message wakes it. A resume inside the warm window is a container start; a colder resume restores the workspace from object storage first. Files can be downloaded from a sleeping session without waking it.

How is usage metered?

A credit is one minute of awake session time. Sleeping sessions cost nothing. T0 meters awake session-seconds, peak workspace bytes and turns; token counts are recorded and shown to you for your own visibility but, under bring-your-own-key, are not billed by T0.

Check live usage any time with GET https://api.t0.sikasio.com/v1/usage.

Is there a free plan?

Yes, permanently. Free is $0 for 300 credits a month (5 h of awake session time), 60 a day, 1 concurrent session, 2 GB of workspace storage and a 7-day retention window. No card required.

What are the plans and quotas?

Free — $0: 300 credits/month (5 h), 60/day, 1 concurrent session, 2 GB storage, 7-day retention, 1 GB / 1 CPU sandbox.

Starter — $19/month: 3,600 credits/month (60 h), 600/day, 3 concurrent sessions, 25 GB storage, 30-day retention, 2 GB / 1.5 CPU sandbox.

Pro — $59/month: 18,000 credits/month (300 h), 2,400/day, 10 concurrent sessions, 100 GB storage, 90-day retention, 4 GB / 2 CPU sandbox.

What happens when I hit a quota?

A hard stop with an upgrade prompt, never a surprise bill. Requests past a quota return 429 quota_exceeded naming the limit you hit and the next plan up; requests past the per-key rate limit return 429 rate_limited with a Retry-After header. Sessions already awake are not killed mid-turn.

How do I stream a response?

POST a message to https://api.t0.sikasio.com/v1/sessions/:id/messages — it returns 202 with a turn_id immediately — and read events from GET https://api.t0.sikasio.com/v1/sessions/:id/events, which is Server-Sent Events. Events are ordered and sequence-numbered per session, so if the connection drops you reconnect with a Last-Event-ID header carrying the last sequence you saw and the stream resumes from there with nothing lost or repeated.

If you would rather push and pull over one connection, https://api.t0.sikasio.com/v1/sessions/:id/socket is a WebSocket that carries the same events and accepts messages and interrupts.

How do I get files in and out?

Small files go straight to the API: PUT the raw body to /v1/sessions/:id/files/<path> and it is streamed into the live workspace. Bulk uploads go as a tar.gz to POST /v1/sessions/:id/files. Large transfers are handed a presigned object-storage URL so the bytes never pass through our servers.

Every path is resolved and confined to /workspace before it reaches the container; traversal is rejected with 400 invalid_path.

How isolated is a session?

Each session is its own container: read-only root filesystem, all Linux capabilities dropped, no-new-privileges, a seccomp profile, a pids limit, and hard memory and CPU ceilings set by your plan. It runs as a non-root user and never sees a Docker socket, a host mount or host networking.

Egress is default-deny through an allowlist proxy that refuses every private network range, so a session can reach the model provider and — depending on plan — package registries, and nothing else. The proxy fails closed: if it is down, the sandbox has no network at all.

Where do I see whether T0 is up?

The status page at https://status.t0.sikasio.com shows live component health — gateway, runner, warm-pool depth, queue depth and recent error rate — plus incident notes. It is served from its own host so it stays up when the stack it reports on does not.

What does a first request look like?

curl -X POST https://api.t0.sikasio.com/v1/sessions -H "Authorization: Bearer t0k_live_YOUR_KEY" -H "Content-Type: application/json" -d '{"name":"my-first-session"}' — that returns a session id and a stream URL, and the session is ready in under a second because it comes from a pool of pre-booted containers.

Get a key

The free plan is permanent: 300 credits a month — 5 h of awake session time — 2 GB of workspace storage and a 7-day retention window, with no card required. Bring your own provider key and you are running in a minute.

Get your free API key →

Questions, or something in these docs that does not match what the API did? support@t0.sikasio.com. Health at https://api.t0.sikasio.com/health, live component status at status.t0.sikasio.com.