Skip to main content
Events

Send events

Send user or system 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
system.messagecontentcontent must be a non-empty array of text content blocks. At most one system.message per request, and it must be the final event of the batch, immediately following user.message, user.tool_result, or user.custom_tool_result
Plain string events[].content is not supported. When an event has a content field, send it as an array of content blocks. Message content blocks lists the block types and fields accepted by each event.

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."}
        ]
      }
    ]
  }'

Send image messages

The following JSON request bodies show the three image sources. See Message content blocks for fields and limits.

Inline Base64

Replace data with raw Base64 image data, without a data:image/png;base64, prefix. Set media_type to match the image format.
{
  "events": [
    {
      "type": "user.message",
      "content": [
        {"type": "text", "text": "Describe this image."},
        {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": "<raw Base64 image data>"}}
      ]
    }
  ]
}

HTTPS image URL

Replace the URL with an external HTTPS image URL readable by the model service.
{
  "events": [
    {
      "type": "user.message",
      "content": [
        {"type": "text", "text": "Describe this image."},
        {"type": "image", "source": {"type": "url", "url": "https://example.com/image.png"}}
      ]
    }
  ]
}

Uploaded image reference

Use Upload file to obtain an accessible image File ID with status ready.
{
  "events": [
    {
      "type": "user.message",
      "content": [
        {"type": "text", "text": "Describe this image."},
        {"type": "image", "source": {"type": "file", "file_id": "file_..."}}
      ]
    }
  ]
}

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 processing a turn

While a Session is running or rescheduling, a new user.message is not queued behind the current turn and returns 409. Wait for session.status_idle, or cancel the current turn first:
{
  "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.