Skip to main content
Sessions

Send events

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

ParameterTypeDescription
session_idstringSession ID with the sess_ prefix

Headers

HeaderRequiredDescription
AuthorizationYesBearer $QODER_ACCESS_TOKEN
Content-TypeYesapplication/json

Request body

FieldTypeRequiredDescription
eventsarrayYesNon-empty array of event objects

Supported event types

TypeRequired fieldsNotes
user.messagecontentcontent must be a non-empty array of content blocks
user.interruptnonesession_thread_id is optional
user.tool_confirmationtool_use_id, resultresult must be allow or deny. deny_message is optional and only allowed when result = "deny"
user.tool_resulttool_use_idReturn 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_resultcustom_tool_use_idReturn 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_outcomedescription, rubricrubric 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
Plain string events[].content is not supported. When an event has a content field, send it as an array of content blocks.

Example request

curl -X POST https://api.qoder.com/api/v1/cloud/sessions/sess_019e392c0d1e74e095d21ea4c6b41def/events \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "type": "user.message",
        "content": [
          {"type": "text", "text": "Help me analyze the performance of this code."}
        ]
      }
    ]
  }'

Example response

HTTP 200 OK
{
  "data": [
    {
      "id": "evt_019e3bb2c153764da54e4d3acbef52b6",
      "type": "user.message",
      "content": [
        {"type": "text", "text": "Help me analyze the performance of this code."}
      ],
      "processed_at": "2026-05-18T15:27:11.187413896Z"
    }
  ]
}

Human-in-the-loop responses

When the stream emits an agent.tool_use that requires confirmation, reply with user.tool_confirmation:
{
  "events": [
    {
      "type": "user.tool_confirmation",
      "tool_use_id": "evt_01JZ6Q3FB6SG8F7J1M2N",
      "result": "deny",
      "deny_message": "Do not delete files in this directory."
    }
  ]
}
For a self-hosted Environment, a worker that executes a built-in tool returns the result with user.tool_result. Set tool_use_id to the agent.tool_use event id:
{
  "events": [
    {
      "type": "user.tool_result",
      "tool_use_id": "evt_01JZ6Q3FB6SG8F7J1M2N",
      "content": [{"type": "text", "text": "Command completed successfully."}],
      "is_error": false
    }
  ]
}
When the stream emits agent.custom_tool_use, execute the tool in your client and reply with user.custom_tool_result:
{
  "events": [
    {
      "type": "user.custom_tool_result",
      "custom_tool_use_id": "evt_01JZ6R1V9Z8K2M3N4P5Q",
      "content": [{"type": "text", "text": "Order status: shipped"}]
    }
  ]
}

Errors

HTTPTypeTrigger
400invalid_request_errorEmpty events, unsupported event type, missing required field, invalid content blocks, or unsupported legacy field
401authentication_errorPAT or SAT invalid or expired
404not_found_errorSession or pending action does not exist
409invalid_request_errorSession 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:
{
  "error": {
    "message": "Field 'content' must be a non-empty array of content blocks.",
    "type": "invalid_request_error"
  },
  "request_id": "2c9d3d8a-dd0f-4c27-b2ad-24c8719c97e1",
  "type": "error"
}

Example: 404 Session not found

{
  "error": {
    "message": "Session 'sess_doesnotexist_xxxxxxxxxxxxxxxxxxxxxxxx' was not found.",
    "type": "not_found_error"
  },
  "request_id": "590c2a0c-1656-42d3-ba0c-32c755d22e77",
  "type": "error"
}

Example: 409 Session is running

Sending a user.message while the Session is already processing a turn:
{
  "error": {
    "message": "Session is currently processing a turn. Cancel the current turn or wait for completion.",
    "type": "invalid_request_error"
  },
  "request_id": "ba018d2f-d6b0-4bbe-a53c-2241baca34fe",
  "type": "error"
}
See Errors for the full error envelope.