Skip to main content
POST
Take a Converse turn (streaming)

Behavior

The response is a Server-Sent Events stream, not JSON. Each frame is event: <type>, then data: <json>, then a blank line, and every stream ends with exactly one turn_end or error frame. A failure before the first frame is a normal JSON error; after it, the status is already 200 and the failure arrives as an error frame. tool_results and confirmations must cover exactly the call ids the paused turn is waiting for: no missing ids, no extras, no duplicates. A new message while a turn is paused is 409 pending_turn with details.pause_kind and details.pending_call_ids. The turn keeps running if the client disconnects. One segment may run for up to 10 minutes. Turn requests have their own rate limit bucket per org: 300 requests per minute, or the deployment’s default limit when that is higher. Every frame, the turn state model, and every stop reason are on Turns and streaming. Resumes are on Client tools and confirmations.

Authorizations

Authorization
string
header
required

Send the key as Authorization: Bearer <key>. Two kinds of key exist.

Organization keys are issued in the portal (Settings, then API keys), each bound to one environment, shaped nx_<environment slug>_<64 hex>. They carry no capabilities and pass every capability check, with one exception: routes under /api/v1/records, /api/v1/engines/{id}/opportunities, /api/v1/graph and /api/v1/catalog/documents accept an organization key only when its environment is live, and refuse any other with 403 scoped_key_required. Revocation takes effect within 60 seconds.

Scoped keys are issued by Nexio on request, shaped nxsk_v1_<24 hex key id>_<43 character secret>. Each is bound to one org, one environment, a set of engines and a set of capabilities. A malformed, unknown or revoked nxsk_ key fails with 401 and is never retried as an organization key. Revocation takes effect on the next request. A scoped key without a route's capability gets 403 insufficient_capability; a scoped key not bound to the engine gets 403 engine_binding_forbidden.

Key-grantable capabilities: engines:read, runs:write, runs:read, runs:defensibility:read, runs:test, catalog:read, catalog:documents:read, webhooks:manage, conversations:use, conversations:export, records:read, records:opportunities:run, actions:write, actions:read, graph:read, records:analyze.

Routes that accept organization keys only (every scoped key gets 403 insufficient_capability): environment management, engine create, update, configuration and publish, and conversation instance authoring. Each operation description names the capability a scoped key needs.

Path Parameters

instance_slug
string
required

Conversation instance identifier slug (e.g. platform-assistant).

conversation_id
string<uuid>
required

Body

application/json
end_user
string
required

The asserted end-user identity the conversation must belong to; required on every turn. A missing assertion is a 400, a mismatch a 404.

message
string

New end-user input (at most 32000 characters; longer messages reject with message_too_long). Leading and trailing spaces are trimmed; a blank message answers invalid_turn_request. Exactly one of the three starters.

Maximum string length: 32000
edit_of_message_id
string<uuid>

Revises the referenced user message: the value of message is stored as a sibling version of that message, and the new branch is served from then on. Requires message; omit it on an ordinary turn.

attachment_ids
string<uuid>[]

Attachments this message carries. Each must already be uploaded to this conversation and belong to the same end user; the platform loads the bytes and hands the files to the model. Requires message, and is rejected alongside tool_results or confirmations.

A named attachment that is missing, out of scope, or not yet readable fails the whole turn rather than running it with fewer documents than were attached. An attachment that is a container (an email or a zip) resolves to the files inside it. The combined bytes are capped at the provider request limit; over it returns 413.

tool_results
object[]

Client-tool results completing a tool_use handoff.

confirmations
object[]

Decisions resolving a pending_confirmation pause.

page_context
any

Untrusted consumer page context, any JSON value, at most 16384 bytes. Sent to the model as a delimited data block on every round of this segment; never stored.

Response

A Server-Sent Events stream of the instance turn. Frames are event: <type> with a JSON data: payload.

SSE frames, each event: <type> then data: <json> then a blank line. Every payload carries type. attachment ({type, message_id, attachments: [{id, name, media_type, notice?}]}) comes first, only when the message carries files. conversation ({type, conversation_id, turn_id, user_message_id?}) comes first otherwise; user_message_id is absent on a resume. Then any of guardrail ({type, rule_id, decision}, decision refused, escalated, output_check_triggered), text_delta ({type, text}), tool_activity ({type, tool_call_id, name, execution, phase}, execution platform or client, phase started, completed, failed), tool_use ({type, tool_call_id, name, input}, client tools only), component ({type, component, version, props}), pending_confirmation ({type, tool_call_id, name, input, reason, execution}). Exactly one terminal frame ends the segment: turn_end ({type, stop_reason, usage}) or error ({type, code, message, reason?}; codes include provider_error, provider_unavailable, invalid_conversation_history, attachment_changed, attachment_read_failed, attachments_unavailable and internal_error). usage is cumulative across the turn's segments and has the six token fields of the stateless converse route. stop_reason is a provider value (end_turn, max_tokens) or one of tool_use, pending_confirmation, refusal, escalated, output_check_triggered, max_output_tokens.

Last modified on September 25, 2026