SandboxREST APISessions, backends and intelligence routes

Sessions, backends and intelligence routes

Create and stream coding-agent sessions, approve plans, list the coding agents and models your key can use, and request intelligence reports.

Every route is on https://sandbox.tangle.tools and takes your account API key as Authorization: Bearer <key> unless it says otherwise. Errors use the shape in Error codes. This page is generated from the OpenAPI document, which also has every response schema.

Sessions

RouteDoes
POST /v1/session/{sessionId}/broadcastBroadcast an event to a session
PUT /v1/session/{sessionId}/mappingMap a session to its runtime session
DELETE /v1/session/{sessionId}/mappingRemove a session’s runtime mapping
POST /v1/sessionsCreate a session
GET /v1/sessions/{id}Get session details
DELETE /v1/sessions/{id}End a session
GET /v1/sessions/{id}/eventsSubscribe to session events (SSE)
POST /v1/sessions/{id}/messageSend a message to a session and stream events
GET /v1/sessions/{id}/messagesList messages for a session
GET /v1/sessions/{id}/turns/{turnId}Look up a cached turn result by idempotency key

Broadcast an event to a session

POST /v1/session/{sessionId}/broadcast

Sends an event to the caller’s connected WebSocket session. If the session is not connected, the event is buffered for delivery on connect. success reports whether the event was delivered or buffered.

ParameterInRequiredTypeDescription
sessionIdpathYesstringSession ID

Request body (application/json):

FieldTypeRequiredDescription
typestringYesEvent type.
idstringNoEvent ID the receiver can use to deduplicate.
dataobjectNoEvent payload.
channelstringNoDeliver only to subscribers of this channel.
StatusMeaning
200The broadcast result
400The session ID or the body is invalid (VALIDATION_ERROR, INVALID_SESSION_ID)
401Missing or invalid credential
403The credential is restricted to its own sandbox (SANDBOX_KEY_RESOURCE_FORBIDDEN)
503The sandbox service did not answer; retry shortly

Map a session to its runtime session

PUT /v1/session/{sessionId}/mapping

Registers which runtime session serves the session ID, so session events are filtered and delivered to the right subscribers.

ParameterInRequiredTypeDescription
sessionIdpathYesstringSession ID

Request body (application/json):

FieldTypeRequiredDescription
sidecarSessionIdstringYesThe runtime’s own session ID (a UUID).
sidecarIdstringNoContainer ID, for direct routing.
projectRefstringNoProject reference, for stale-runtime checks.
StatusMeaning
200The mapping was recorded
400The session ID or the body is invalid (VALIDATION_ERROR, INVALID_SESSION_ID)
401Missing or invalid credential
403The credential is restricted to its own sandbox (SANDBOX_KEY_RESOURCE_FORBIDDEN)
404The mapping was rejected
410The runtime is gone and must be reprovisioned
503The sandbox service did not answer; retry shortly

Remove a session’s runtime mapping

DELETE /v1/session/{sessionId}/mapping

Removes the mapping and stops event subscriptions for the session.

ParameterInRequiredTypeDescription
sessionIdpathYesstringSession ID
StatusMeaning
200The mapping was removed
400The session ID or the body is invalid (VALIDATION_ERROR, INVALID_SESSION_ID)
401Missing or invalid credential
403The credential is restricted to its own sandbox (SANDBOX_KEY_RESOURCE_FORBIDDEN)
404The session has no mapping
503The sandbox service did not answer; retry shortly

Create a session

POST /v1/sessions

Request body (application/json):

FieldTypeRequiredDescription
projectIdstringNo
configobjectNo
interactionsobjectNo
StatusMeaning
201Session created
400Invalid request
402KEY_BUDGET_EXHAUSTED: the Platform key funding the sandbox has no budget left
403Driver not allowed, or PROFILE_SECRET_ISOLATION_UNAVAILABLE: backend.metadata.profileSecretIsolation needs an existing sandbox whose runtime seals the secret launch
404Sandbox not found
413Request body exceeds the proxy wire limit
429Quota exceeded
500Internal error
502Upstream proxy error
503Runtime host unavailable, or PROFILE_SECRET_ISOLATION_UNAVAILABLE with reason sidecar_unreachable: the sandbox’s runtime could not be asked; retry after Retry-After

Get session details

GET /v1/sessions/{id}

ParameterInRequiredTypeDescription
idpathYesstringSession ID
StatusMeaning
200Session details
400Invalid request
403Driver not allowed
404Session not found
500Upstream proxy error
502Upstream proxy error

End a session

DELETE /v1/sessions/{id}

ParameterInRequiredTypeDescription
idpathYesstringSession ID
StatusMeaning
200Session ended
400Invalid request
403Driver not allowed
404Session not found
500Upstream proxy error
502Upstream proxy error
503Sandbox billing state is temporarily unavailable

Subscribe to session events (SSE)

GET /v1/sessions/{id}/events

ParameterInRequiredTypeDescription
idpathYesstringSession ID
StatusMeaning
200SSE stream
400Invalid request
403Driver not allowed
404Session not found

Send a message to a session and stream events

POST /v1/sessions/{id}/message

ParameterInRequiredTypeDescription
idpathYesstringSession ID

Request body (application/json):

FieldTypeRequiredDescription
messagestringYes
StatusMeaning
200Server-Sent Events stream
400Invalid request
403Driver not allowed
404Session not found
409The sandbox was created without an agent
413Message body exceeds the proxy wire limit
500Internal error
502Upstream proxy error
503Model credential is being updated; retry shortly

List messages for a session

GET /v1/sessions/{id}/messages

Returns the session message log including in-flight assistant content. Each run’s assistant message carries metadata.status (streaming / completed / interrupted).

ParameterInRequiredTypeDescription
idpathYesstringSession ID
limitqueryNointeger
offsetqueryNointeger or null
sincequeryNointeger or null
StatusMeaning
200Message list
400Invalid request
403Driver not allowed or insufficient access
404Session not found
500Internal error
502Upstream proxy error

Look up a cached turn result by idempotency key

GET /v1/sessions/{id}/turns/{turnId}

Returns the cached AgentExecutionResult for a previously-completed turn on this session, or 404 if no such completion exists. Callers use this to short-circuit retries whose original attempt already finished.

ParameterInRequiredTypeDescription
idpathYesstring
turnIdpathYesstring
StatusMeaning
200Cached turn result
400Invalid request
403Driver not allowed or insufficient access
404Session or turn not found
500Internal error
502Upstream proxy error

Durable plans

RouteDoes
POST /v1/plan-followups/{planId}/admissionAdmit a plan follow-up turn
POST /v1/plan-submissionsSubmit a plan for approval
POST /v1/plan-submissions/{planId}/confirmationConfirm a submitted plan
POST /v1/plan-submissions/{planId}/withdrawalWithdraw a submitted plan
GET /v1/sandboxes/{projectRef}/agent-sessions/{agentSessionId}/plans/currentGet the current plan of an agent session
GET /v1/sandboxes/{projectRef}/agent-sessions/{agentSessionId}/plans/{planId}Get a plan
POST /v1/sandboxes/{projectRef}/agent-sessions/{agentSessionId}/plans/{planId}/decisionApprove or reject a plan

Admit a plan follow-up turn

POST /v1/plan-followups/{planId}/admission

Authenticated by the x-tangle-plan-followup-credential header, not by a bearer token.

Authentication: none.

ParameterInRequiredTypeDescription
planIdpathYesstringPlan ID
x-tangle-plan-followup-credentialheaderYesstringFollow-up credential from the plan decision’s resume

Request body (application/json):

FieldTypeRequiredDescription
turnIdstringYes
executionIdstringYes
continuationobjectYes
StatusMeaning
200Follow-up admitted
400Invalid admission (INVALID_REQUEST)
401The credential is missing or invalid (PLAN_FOLLOWUP_CREDENTIAL_INVALID)
404Plan not found (PLAN_NOT_FOUND)
409The follow-up cannot be admitted in its current state
413The request body is over the proxy limit

Submit a plan for approval

POST /v1/plan-submissions

Authenticated by the x-tangle-plan-submission-credential header, not by a bearer token. A repeat with the same sourceTurnId and sourceToolCallId returns the same plan. Approvers cannot see the plan until it is confirmed. A session whose backend isolates profile secrets is refused.

Authentication: none.

ParameterInRequiredTypeDescription
x-tangle-plan-submission-credentialheaderYesstringPlan submission credential issued for the agent session

Request body (application/json):

FieldTypeRequiredDescription
projectRefstringYes
agentSessionIdstringYes
sourceTurnIdstringYes
sourceToolCallIdstringYes
titlestringNo
bodystringYes
providerStateobjectYes
backendConfigobjectNo
StatusMeaning
201Plan submitted
400Invalid submission (INVALID_REQUEST, PLAN_BODY_REQUIRED, PLAN_SOURCE_ID_REQUIRED, PLAN_PROVIDER_STATE_INVALID)
401The credential is missing, invalid or expired (PLAN_SUBMISSION_CREDENTIAL_INVALID, PLAN_SUBMISSION_CREDENTIAL_EXPIRED)
403The backend isolates profile secrets (PROFILE_SECRET_ISOLATION_UNAVAILABLE)
409The plan cannot take this change in its current state (PLAN_SUBMISSION_CONFLICT, PLAN_NOT_READY, PLAN_SUPERSEDED, PLAN_WITHDRAWN, PLAN_ALREADY_DECIDED)
413The request body is over the proxy limit

Confirm a submitted plan

POST /v1/plan-submissions/{planId}/confirmation

Authenticated by the x-tangle-plan-submission-credential header, not by a bearer token. Makes the plan visible to approvers and supersedes the session’s earlier plans.

Authentication: none.

ParameterInRequiredTypeDescription
planIdpathYesstringPlan ID
x-tangle-plan-submission-credentialheaderYesstringPlan submission credential issued for the agent session
StatusMeaning
200Plan confirmed
401The credential is missing, invalid or expired (PLAN_SUBMISSION_CREDENTIAL_INVALID, PLAN_SUBMISSION_CREDENTIAL_EXPIRED)
404Plan not found (PLAN_NOT_FOUND)
409The plan cannot take this change in its current state (PLAN_SUBMISSION_CONFLICT, PLAN_NOT_READY, PLAN_SUPERSEDED, PLAN_WITHDRAWN, PLAN_ALREADY_DECIDED)
413The request body is over the proxy limit

Withdraw a submitted plan

POST /v1/plan-submissions/{planId}/withdrawal

Authenticated by the x-tangle-plan-submission-credential header, not by a bearer token.

Authentication: none.

ParameterInRequiredTypeDescription
planIdpathYesstringPlan ID
x-tangle-plan-submission-credentialheaderYesstringPlan submission credential issued for the agent session

Request body (application/json):

FieldTypeRequiredDescription
reasonstringYes
StatusMeaning
200Plan withdrawn
400Invalid request (INVALID_REQUEST, PLAN_WITHDRAWAL_REASON_REQUIRED)
401The credential is missing, invalid or expired (PLAN_SUBMISSION_CREDENTIAL_INVALID, PLAN_SUBMISSION_CREDENTIAL_EXPIRED)
404Plan not found (PLAN_NOT_FOUND)
409The plan cannot take this change in its current state (PLAN_SUBMISSION_CONFLICT, PLAN_NOT_READY, PLAN_SUPERSEDED, PLAN_WITHDRAWN, PLAN_ALREADY_DECIDED)
413The request body is over the proxy limit

Get the current plan of an agent session

GET /v1/sandboxes/{projectRef}/agent-sessions/{agentSessionId}/plans/current

Needs read access to the sandbox. A plan not confirmed is not found.

ParameterInRequiredTypeDescription
projectRefpathYesstringSandbox ID
agentSessionIdpathYesstringAgent session ID
StatusMeaning
200Current plan
403The credential or team role cannot use this sandbox
404Plan not found (PLAN_NOT_FOUND)

Get a plan

GET /v1/sandboxes/{projectRef}/agent-sessions/{agentSessionId}/plans/{planId}

Needs read access to the sandbox. A plan not confirmed is not found.

ParameterInRequiredTypeDescription
projectRefpathYesstringSandbox ID
agentSessionIdpathYesstringAgent session ID
planIdpathYesstringPlan ID
StatusMeaning
200Plan
403The credential or team role cannot use this sandbox
404Plan not found (PLAN_NOT_FOUND)

Approve or reject a plan

POST /v1/sandboxes/{projectRef}/agent-sessions/{agentSessionId}/plans/{planId}/decision

Needs write access to the sandbox; a team viewer is refused. Repeating the same decision answers idempotent: true. Send followUp { mode: “caller” } to receive the follow-up turn’s resume credential instead of having the service start the turn.

ParameterInRequiredTypeDescription
projectRefpathYesstringSandbox ID
agentSessionIdpathYesstringAgent session ID
planIdpathYesstringPlan ID

Request body (application/json): one of 2 shapes; see the OpenAPI document.

StatusMeaning
200Decision recorded
400Invalid decision (INVALID_REQUEST, PLAN_REJECTION_FEEDBACK_REQUIRED, PLAN_APPROVAL_FEEDBACK_FORBIDDEN)
403The credential or team role cannot decide this plan (INSUFFICIENT_ROLE, PLAN_DECISION_ACTOR_INVALID)
404Plan not found (PLAN_NOT_FOUND)
409The plan cannot be decided in its current state, or its caller follow-up is leased (PLAN_SUPERSEDED, PLAN_WITHDRAWN, PLAN_ALREADY_DECIDED, PLAN_OUTBOX_LEASE_LOST)
413The request body is over the proxy limit
503Caller follow-up admission is not configured (PLAN_FOLLOWUP_UNAVAILABLE)

Backends

RouteDoes
GET /v1/backendsList available agent backends
GET /v1/router-modelsList the Router model catalog

List available agent backends

GET /v1/backends

Returns the per-backend capability registry (streaming, tool use, reasoning, multimodal, imageInput, MCP, sessions, interactions) and whether a backend runs only on the caller’s own credential. Profiles are supplied inline on execution and provisioning requests.

StatusMeaning
200Backends retrieved successfully
500Internal error

List the Router model catalog

GET /v1/router-models

The Tangle Router’s GET /v1/models rows, read with the caller’s managed Router key, so the list is the models this caller can run.

StatusMeaning
200Router model catalog
502The Router refused or failed
503No Router key can be minted

Intelligence

RouteDoes
POST /v1/intelligence/reportsCreate an intelligence report
GET /v1/intelligence/reportsList intelligence reports
POST /v1/intelligence/reports/estimateEstimate an intelligence report
GET /v1/intelligence/reports/{jobId}Get an intelligence report

Create an intelligence report

POST /v1/intelligence/reports

Request body (application/json):

FieldTypeRequiredDescription
subjectobjectYes
mode”deterministic” | “agentic”No
acknowledgeCostbooleanNo
budgetobjectNo
metadataobjectNo
StatusMeaning
201Created intelligence report
400Invalid request
402Payment required

List intelligence reports

GET /v1/intelligence/reports

ParameterInRequiredTypeDescription
subjectTypequeryNo”sandbox” | “fleet”
subjectIdqueryNostring
limitqueryNointeger
StatusMeaning
200Intelligence reports

Estimate an intelligence report

POST /v1/intelligence/reports/estimate

Request body (application/json):

FieldTypeRequiredDescription
subjectobjectYes
mode”deterministic” | “agentic”No
metadataobjectNo
StatusMeaning
200Cost estimate for prospective intelligence report
404Subject not found or not owned by caller

Get an intelligence report

GET /v1/intelligence/reports/{jobId}

ParameterInRequiredTypeDescription
jobIdpathYesstring
StatusMeaning
200Intelligence report
404Not found

Next steps