Send supported user events to a Session.
POST /api/v1/cloud/sessions/{session_id}/events
Sends one or more accepted events to a Session. User messages trigger asynchronous Agent processing; use the list or stream endpoints to read Agent output.
Path parameters
| Parameter | Type | Description |
|---|---|---|
session_id | string | Session ID with the sess_ prefix |
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer $QODER_ACCESS_TOKEN |
Content-Type | Yes | application/json |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
events | array | Yes | Non-empty array of event objects |
Supported event types
| Type | Required fields | Notes |
|---|---|---|
user.message | content | content must be a non-empty array of content blocks |
user.interrupt | none | session_thread_id is optional |
user.tool_confirmation | tool_use_id, result | result must be allow or deny. deny_message is optional and only allowed when result = "deny" |
user.tool_result | tool_use_id | Return a built-in tool result from a self-hosted worker. content is optional; when present, it must be an array of content blocks. is_error is optional |
user.custom_tool_result | custom_tool_use_id | Return a client-side custom tool result. content is optional; when present, it must be an array of content blocks. is_error is optional |
user.define_outcome | description, rubric | rubric is an object: either {"type":"text","content":"..."} or {"type":"file","file_id":"file_..."}; unknown fields are rejected. max_iterations is optional and must be an integer between 1 and 20. The server assigns an outcome_id (prefix outc_) — clients must not pass it |
events[].content is not supported. When an event has a content field, send it as an array of content blocks.
Example request
Example response
HTTP 200 OK
Human-in-the-loop responses
When the stream emits an agent.tool_use that requires confirmation, reply with user.tool_confirmation:
user.tool_result. Set tool_use_id to the agent.tool_use event id:
agent.custom_tool_use, execute the tool in your client and reply with user.custom_tool_result:
Errors
| HTTP | Type | Trigger |
|---|---|---|
| 400 | invalid_request_error | Empty events, unsupported event type, missing required field, invalid content blocks, or unsupported legacy field |
| 401 | authentication_error | PAT or SAT invalid or expired |
| 404 | not_found_error | Session or pending action does not exist |
| 409 | invalid_request_error | Session is currently processing a turn, or other Session state conflict (note: type is invalid_request_error, not conflict_error) |
Example: 400 invalid content
Sending user.message with a plain string instead of a content block array:
Example: 404 Session not found
Example: 409 Session is running
Sending a user.message while the Session is already processing a turn: