> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send session events

> Send user or system input events to a Forward session.

`POST /api/v1/forward/sessions/{session_id}/events`

Adds input events to a session. Forward accepts user input events and controlled system input events; callers cannot forge agent or session status events.

## Headers

| Header            | Required | Description                                   |
| ----------------- | -------- | --------------------------------------------- |
| `Authorization`   | Yes      | `Bearer <PAT>`                                |
| `Content-Type`    | Yes      | `application/json`                            |
| `Idempotency-Key` | No       | Optional idempotency key for unsafe requests. |

## Path parameters

| Parameter    | Type   | Required | Description |
| ------------ | ------ | -------- | ----------- |
| `session_id` | string | Yes      | Session ID. |

## Body parameters

| Parameter                     | Type    | Required    | Description                                                                                |
| ----------------------------- | ------- | ----------- | ------------------------------------------------------------------------------------------ |
| `events`                      | array   | Yes         | Event objects to append.                                                                   |
| `events[].type`               | string  | Yes         | Input Event type.                                                                          |
| `events[].content`            | array   | Conditional | Required for `user.message` and `system.message`; must be a non-empty content block array. |
| `events[].file_attachments`   | array   | No          | File attachment metadata for `user.message`.                                               |
| `events[].tool_use_id`        | string  | Conditional | Required for `user.tool_confirmation` and `user.tool_result`.                              |
| `events[].custom_tool_use_id` | string  | Conditional | Required for `user.custom_tool_result`.                                                    |
| `events[].result`             | string  | Conditional | Required for `user.tool_confirmation`: `allow` or `deny`.                                  |
| `events[].deny_message`       | string  | No          | Denial reason when `result=deny`.                                                          |
| `events[].description`        | string  | Conditional | Required for `user.define_outcome`.                                                        |
| `events[].rubric`             | object  | Conditional | Required for `user.define_outcome`.                                                        |
| `events[].reason`             | string  | No          | Interrupt reason for `user.interrupt`.                                                     |
| `events[].is_error`           | boolean | No          | Error flag for tool result events.                                                         |

## Allowed input event types

```text theme={null}
user.message
user.interrupt
user.tool_confirmation
user.tool_result
user.custom_tool_result
user.define_outcome
system.message
```

## Example request

```bash theme={null}
curl -s -X POST 'https://api.qoder.com/api/v1/forward/sessions/sess_xxx/events' \
  -H "Authorization: Bearer $QODER_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "type": "user.message",
        "content": [
          {
            "type": "text",
            "text": "Continue the analysis."
          }
        ],
        "file_attachments": []
      }
    ]
  }'
```

## Example response

**HTTP 200 OK**

```json theme={null}
{
  "data": [
    {
      "id": "evt_xxx",
      "type": "user.message",
      "session_id": "sess_xxx",
      "content": [
        {
          "type": "text",
          "text": "Continue the analysis."
        }
      ],
      "processed_at": "2026-06-22T11:00:00Z"
    }
  ]
}
```

## Response fields

| Field  | Type  | Description                                    |
| ------ | ----- | ---------------------------------------------- |
| `data` | array | Created Event objects after Forward filtering. |

## Errors

| HTTP | Type                    | Code                              | Trigger                                                     |
| ---- | ----------------------- | --------------------------------- | ----------------------------------------------------------- |
| 400  | `invalid_request_error` | `invalid_event`                   | Event type or fields are invalid.                           |
| 401  | `authentication_error`  | `authentication_required`         | PAT invalid or expired.                                     |
| 404  | `not_found_error`       | `session_not_found`               | Session does not exist.                                     |
| 409  | `conflict_error`        | `session_archived`                | Session is archived.                                        |
| 409  | `conflict_error`        | `turn_already_running`            | Current turn does not allow a new turn.                     |
| 404  | `not_found_error`       | `pending_action_not_found`        | Tool confirmation or result has no matching pending action. |
| 409  | `conflict_error`        | `pending_action_already_resolved` | Pending action was already resolved.                        |

## Notes

* `system.message` is limited to one per request, must be the last event, and must follow `user.message`, `user.tool_result`, or `user.custom_tool_result`.
* The response uses the filtered Forward Event object and does not expose raw runtime event JSON.

## Related

<CardGroup cols={2}>
  <Card title="List session events" icon="list" href="/cloud-agents/api/forward/sessions/list-events" />

  <Card title="Stream session events" icon="radio" href="/cloud-agents/api/forward/sessions/stream-events" />
</CardGroup>
