AI API Guide
Session contract
A Session (ses_*) runs one saved Agent version and is created directly with POST /v1/agents/sessions. Internal Runtime Session IDs are not exposed.
A single-page guide to the most common API workflows. For the complete machine-readable contract, use the OpenAPI specification. Plain-text version:
llms-full.txt.
Authentication
All requests require:
Authorization: Bearer sk-YOUR_KEYBase URL: https://api.sandbase.ai/v1
Terminology
| Term | Meaning |
|---|---|
| Task | A billable execution record for operations such as model inference. Not every API operation creates one. |
| Run | A media generation request via POST /v1/run. May be sync or async. Poll with GET /v1/run/{id}. |
| Session | An Agent execution via POST /v1/agents/sessions, holding the conversation, tool activity, and output. Query with GET /v1/agents/sessions/{session_id}. |
run vs session: A model "run" (
/v1/run) is a model generation task. A "Session" (/v1/agents/sessions) is an Agent execution. All IDs are opaque and must not be parsed.task vs run: A "run" or "session" is the request you make; a "task" is a billable execution record. Use
GET /v1/tasks/{task_id}/costwhen an operation returns a task ID. Not every API operation creates a task.
Chat Completions
POST /v1/chat/completions
OpenAI-compatible. Streaming, tools, vision, reasoning, and structured-output support depend on the selected model and its declared schema.
curl https://api.sandbase.ai/v1/chat/completions \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.6-luna",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain quantum computing in one paragraph."}
],
"temperature": 0.7,
"max_tokens": 500,
"stream": false
}'Response:
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"model": "openai/gpt-5.6-luna",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Quantum computing leverages quantum mechanical phenomena..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 24,
"completion_tokens": 89,
"total_tokens": 113
}
}Some billable operations may return
x-task-id: f3d2e8a1-7c4b-4a12-9d2e-123456789abc; when present, use it to queryGET /v1/tasks/f3d2e8a1-7c4b-4a12-9d2e-123456789abc/cost.
Anthropic Messages
POST /v1/messages
Anthropic-compatible Messages API. Caching and other optional features depend on the selected model and request schema.
curl https://api.sandbase.ai/v1/messages \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "What is SandBase?"}]
}'Response:
{
"id": "msg_abc123",
"type": "message",
"role": "assistant",
"content": [
{ "type": "text", "text": "SandBase is an AI agent infrastructure platform..." }
],
"model": "anthropic/claude-sonnet-5",
"stop_reason": "end_turn",
"usage": { "input_tokens": 12, "output_tokens": 64 }
}Image Generation
POST /v1/run
The /v1/run endpoint is a unified generation endpoint — the model field determines the output type (image, video, or audio).
How to handle the response: Check the
statusfield.
"completed"→ results are inoutputs, done."pending"or"running"→ pollGET /v1/run/{id}every 2–5s until a terminal status (completed,failed, ortimeout).
curl https://api.sandbase.ai/v1/run \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bfl/flux-2/flash",
"prompt": "A futuristic city at sunset, cyberpunk style",
"aspect_ratio": "1:1"
}'Response (sync):
{
"id": "f3d2e8a1-7c4b-4a12-9d2e-123456789abc",
"status": "completed",
"model": "bfl/flux-2/flash",
"created_at": "2026-08-02T12:00:00Z",
"outputs": [{
"url": "https://cdn.sandbase.ai/outputs/f3d2e8a1-7c4b-4a12-9d2e-123456789abc.png",
"content_type": "image/png",
"width": 1024,
"height": 1024
}]
}Video Generation
POST /v1/run
Check the selected model's execution_mode. When submission returns pending or running, poll GET /v1/run/{id} until a terminal status.
curl https://api.sandbase.ai/v1/run \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kwaivgi/kling-video/v3/standard/text-to-video",
"prompt": "A drone flying over mountains at golden hour",
"duration": 5
}'Response (async — initial):
{
"id": "6a7b9c10-2d3e-4f50-8a61-23456789abcd",
"status": "running",
"model": "kwaivgi/kling-video/v3/standard/text-to-video",
"created_at": "2026-08-02T12:00:00Z"
}Poll status: GET /v1/run/{id}
{
"id": "6a7b9c10-2d3e-4f50-8a61-23456789abcd",
"status": "completed",
"outputs": [{
"url": "https://cdn.sandbase.ai/outputs/6a7b9c10-2d3e-4f50-8a61-23456789abcd.mp4",
"content_type": "video/mp4",
"duration": 5
}]
}Audio (Text-to-Speech)
POST /v1/run
curl https://api.sandbase.ai/v1/run \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bytedance/seed-speech/tts/2.0",
"text": "Hello world, this is a test of text to speech."
}'Response:
{
"id": "7b8c0d21-3e4f-5061-9b72-3456789abcde",
"status": "completed",
"model": "bytedance/seed-speech/tts/2.0",
"created_at": "2026-08-02T12:00:00Z",
"outputs": [{
"url": "https://cdn.sandbase.ai/outputs/7b8c0d21-3e4f-5061-9b72-3456789abcde.mp3",
"content_type": "audio/mpeg",
"duration_seconds": 3.2
}]
}List Models
GET /v1/models
Returns enabled logical models in the OpenAI-compatible model-list format. The endpoint is not paginated and defaults to type=llm. Detailed capabilities and pricing are intentionally omitted.
curl https://api.sandbase.ai/v1/models \
-H "Authorization: Bearer sk-YOUR_KEY"The response contains object: "list" and a data array. Each item contains id, object, created, and owned_by; use id as the logical model name. Retrieve that model for capability and pricing metadata.
Get Model
GET /v1/models/
curl https://api.sandbase.ai/v1/models/openai/gpt-5.6-luna \
-H "Authorization: Bearer sk-YOUR_KEY"The detail response adds unified_schema, supported_modes, and model_card. Detailed prices live inside model_card; there is no top-level pricing object.
Get Task Cost
GET /v1/tasks/{task_id}/cost
Check the recorded cost of a task using the task ID returned by the API operation.
curl https://api.sandbase.ai/v1/tasks/f3d2e8a1-7c4b-4a12-9d2e-123456789abc/cost \
-H "Authorization: Bearer sk-YOUR_KEY"Response:
{
"id": "f3d2e8a1-7c4b-4a12-9d2e-123456789abc",
"status": "completed",
"settled": true,
"currency": "USD",
"cost": "0.000325",
"estimated_cost": "0.000325",
"usage": {
"prompt_tokens": 24,
"completion_tokens": 89,
"total_tokens": 113,
"cached_tokens": 0,
"cache_creation_tokens": 0,
"reasoning_tokens": 0
}
}Agents platform conventions
Base URL
https://api.sandbase.ai/v1. SendAuthorization: Bearer sk-YOUR_KEYorX-API-Key: sk-YOUR_KEY(same value if both).OpenAI-Betais optional; if sent it must beagents=v1. The official OpenAI SDK (client.beta.agents,client.skills) works withbase_url="https://api.sandbase.ai/v1"; differences are listed in OpenAI compatibility.Bodies are strict JSON up to 1 MiB; unknown fields return 400.
Errors:
{"error":{"type":"invalid_request_error","code":"conflict","param":null,"message":"conflicting request"}}. Branch oncode; see the Error Guide.row_versionis the compare-and-set token for PATCH, archive, restore, and rotate. On 409, read again.Cursor lists (Agents, Sessions, items, turns, Skills):
limit1-100,after,order; response{object:"list", data, has_more, first_id, last_id}.Offset lists (Agent versions, attachments, MCP connections, Secrets):
limit,offset; response{data, total, limit, offset}.IDs: Agent
agt_, Sessionses_, Skillskl_, MCP connectionmcp_, Secretsec_, attachmentfil_. Treat them as opaque.
Agents
POST /v1/agents — Create Agent
curl -X POST https://api.sandbase.ai/v1/agents \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Idempotency-Key: create-research-agent-1" \
-H "Content-Type: application/json" \
-d '{
"name": "Research assistant",
"model": "deepseek/deepseek-v4-flash",
"instructions": "Research the question and cite sources."
}'Required: model. Optional: name, instructions, description, runtime_profile (codex default, claude, mcode), skills ([{"skill_id","version"}]), mcp_connections ([{"connection_id","server_label","allowed_tools","required"}]), tools, text, reasoning, service_tier, metadata, note. Returns 201 with id (agt_), version, row_version, status, and projection_status; start Sessions when projection_status is ready. web_search tools must use mode: "disabled", and client-side function results (requires_action) are not supported.
GET /v1/agents — List Agents
Query status (active default, archived, all) plus cursor pagination.
GET /v1/agents/{agent_id} — Get Agent
POST /v1/agents/{agent_id} — Update Agent (SDK style)
Partial update of name, instructions, model, metadata, service_tier, tools, text, reasoning, runtime_profile, mcp_connections, skills. No row_version; creates a new version.
PATCH /v1/agents/{agent_id} — Update Agent (compare-and-set)
Same fields plus description and note; row_version is required. Explicit null returns 400.
Versions, archive, restore, catalog
GET /v1/agents/{agent_id}/versionsandGET /v1/agents/{agent_id}/versions/{version}read immutable snapshots.POST /v1/agents/{agent_id}/archive,POST /v1/agents/{agent_id}/unarchivetake{"row_version"}.DELETE /v1/agents/{agent_id}also archives.POST /v1/agents/{agent_id}/restoretakes{"source_version","row_version"}.GET /v1/agents/cataloglists public Agents;POST /v1/agents/catalog/{agent_id}/clonecopies one into your organization (201, newagt_).
Sessions
A Session runs one saved Agent version. Paths are under /v1/agents/sessions. The Agent version, Skill versions, and MCP connections are frozen at creation.
POST /v1/agents/sessions — Create Session
curl -X POST https://api.sandbase.ai/v1/agents/sessions \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"agent_id": "agt_..."}'Send agent_id (saved Agent), agent (inline Agent or per-Session overrides of model, instructions, runtime_profile, service_tier, tools, text, reasoning, and multi_agent), or both. Optional: version (saved Agents only), title, input (a string, or an array with exactly one user message containing one input_text part), model or agent.model, metadata, model_provider ({"type":"custom","base_url":"https://...","api_key":"..."}; omitted means your calling key). stream: true with a non-empty input returns 201 as a Server-Sent Events stream of the first turn, starting with agent.session.created. Sessions always run in SandBase's hosted cloud, so there is no environment to choose; the OpenAI SDK still requires environment={"type": "openai_hosted"}. Returns 201 with status (idle, in_progress, failed), lifecycle_status (active, archived), failure, source (direct, service, schedule), and row_version.
GET /v1/agents/sessions/{session_id}/events — Stream Events (SSE)
Live-only. Open it before sending input. Last-Event-ID or after returns 400; events are not replayed. Event type values start with agent.session..
POST /v1/agents/sessions/{session_id}/events — Send Input
curl -X POST https://api.sandbase.ai/v1/agents/sessions/ses_.../events \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Idempotency-Key: input-1" \
-H "Content-Type: application/json" \
-d '{"events": [{"type": "agent.session.input.message", "input": "Summarize the findings."}]}'Exactly one event per request: agent.session.input.message or agent.session.input.cancel. Returns 202 with no body. Extension form: {"input": "...", "file_ids": ["fil_..."]} (up to 10 ready attachments). 409 session_input_pending means earlier input is still being delivered; wait and do not resend with a new key.
History and other Session operations
GET /v1/agents/sessions(querylifecycle_status,agent_id),GET /v1/agents/sessions/{session_id}.GET /v1/agents/sessions/{session_id}/items,GET /v1/agents/sessions/{session_id}/turns,GET /v1/agents/sessions/{session_id}/turns/{turn_id}read history.POST /v1/agents/sessions/{session_id}replacesmetadata;PATCH /v1/agents/sessions/{session_id}renames with{"title","row_version"}.POST /v1/agents/sessions/{session_id}/cancel(requiresIdempotency-Key) cancels the running turn.DELETE /v1/agents/sessions/{session_id}archives;POST /v1/agents/sessions/{session_id}/unarchiverestores.POST /v1/agents/sessions/{session_id}/filesuploads one attachment (multipartfile, 5 MiB,Idempotency-Keyrequired).POST /v1/agents/sessions/{session_id}/reconnectreturnsstream_urlforGET /v1/agents/sessions/{session_id}/events/stream, which sendssession.snapshotand then live events.
Workspace files and output artifacts
GET /v1/agents/sessions/{session_id}/workspace-fileslists current file metadata underpath(default/workspace). Querylimit(1-100, default 20),order(ascdefault ordesc), andpage(the previousnextcursor). Returns{object:"page", data:[{path,size_bytes}], next, has_more}. An invalid cursor requires restarting from page one.GET /v1/agents/sessions/{session_id}/artifactslists immutable outputs captured under/workspace/outputs/. Querylimit(default 20),order(descdefault), andafter(uselast_idwhenhas_moreis true).GET /v1/agents/sessions/{session_id}/artifacts/{artifact_id}/contentdownloads a complete artifact using its returned opaqueart_ID. Downloads have a 200 MiB limit;Rangeis unsupported (416). Workspace metadata, uploaded attachments, and captured artifacts are separate resources.
Skills, MCP Connections, and Secrets
POST /v1/skills — Create Skill
curl -X POST https://api.sandbase.ai/v1/skills \
-H "Authorization: Bearer sk-YOUR_KEY" \
-F "files=@release-notes.zip;type=application/zip"One ZIP part files (5 MiB). The ZIP must contain one top-level folder with SKILL.md (name and description frontmatter) inside it, for example zip -r release-notes.zip release-notes/; a SKILL.md at the ZIP root returns 400 invalid_request. A Skill referenced by any Agent version (including archived Agents) cannot be deleted (409); disable it with POST /v1/skills/{skill_id} and {"status": "disabled"} instead. Returns 201 with id (skl_) and default_version. Add versions with POST /v1/skills/{skill_id}/versions; list with GET /v1/skills. Reference from an Agent as {"skill_id": "skl_...", "version": null}.
POST /v1/mcp-connections — Register an MCP server
Body {"name", "server_url" (HTTPS), "secret_id"?}; Idempotency-Key required. Reference from an Agent's mcp_connections. Disabling it blocks new Sessions and further input.
POST /v1/secrets — Store an MCP Bearer token
Body {"name", "kind": "mcp_bearer", "server_url", "token"}; Idempotency-Key required. The token is write-only and bound to that exact URL. Secrets are not environment variables. Rotate with POST /v1/secrets/{secret_id}/rotate; revoke with DELETE /v1/secrets/{secret_id} (204).
Billing & Cost
How costs are calculated
- Read the selected model's current pricing formula and units from its
model_card. - Token-priced models can include input, output, cache, or reasoning components when declared.
- Media and other models can use per-request, duration, resolution, or other model-specific units.
- Data APIs (search, social, scraping, e-commerce, finance) include 100 free calls per organization per UTC day, shared across eligible data APIs and reset at 00:00 UTC. Later calls are billed per call; they are not rejected. Organizations with a zero balance can still use the free calls.
- Not eligible: LLMs, media models, and pricier or formula-priced data APIs (for example some batch endpoints, crawl, Xiaohongshu PGY, and the Douyin Xingtu
kol-*routes), which are billed from the first call.pricing.free_quotaonsandbase_inspectis the check. - MCP:
sandbase_inspectshowspricing.free_quotaon eligible tools;sandbase_accountreturnsfree_api_quota(daily_limit,used_today,remaining,resets_at); settledsandbase_runandsandbase_run_getresults includefree_quota_status(free,overage, ordegraded). - When a billable operation returns a task ID (including an
x-task-idresponse header), useGET /v1/tasks/{task_id}/costfor settlement and usage. - For asynchronous
POST /v1/runresponses, query the generation result withGET /v1/run/{id}; a run ID is not a task ID and must not be sent to the cost endpoint.
Budget control
- Set an optional spending limit when creating or editing a standard key under Developer → API Keys.
- Monitor requests and cost under Developer → Activities → Usage.
- Review balance and credit transactions under Developer → Billing.
See Also
- Models & Pricing — live model discovery, capabilities, and pricing guidance
- Error Guide — documented response shapes, HTTP handling, and retry safety
- OpenAPI Spec — machine-readable schema
Agent Skill version bindings
Saving an Agent pins each new Skill reference to an explicit version. For a new binding, version: null selects the current default at save time. For an existing binding, version: null retains its pinned version. Changing a Skill default does not upgrade saved Agents or existing Sessions; save an explicit version on the Agent to upgrade future Sessions.