---
title: "Create Event"
method: POST
path: "/admin/engagement-internal/events"
tags: ["admin", "engagement-internal"]
---

# Create Event

`POST /admin/engagement-internal/events`

## Request

- Base URL: `https://api-docs.upsmith.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api-docs.upsmith.com/admin/engagement-internal/events`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

## Headers

- `organization-id` string, nullable
- `timezone` string
- `x-user-id` string, nullable
- `x-actor-email` string, nullable
- `x-request-source` string, nullable
- `x-operation-id` string, nullable
- `x-commit-message` string, nullable
- `x-confirmation-id` string, nullable
- `x-chat-id` string, nullable

## Request body

- Event
  - `organization_id` string, required
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `deleted_at` string, date-time, nullable
  - `id` string
  - `engagement_id` string, required
  - `origin` 'internal' | 'external', required
  - `role` 'user' | 'agent' | 'contact' | 'provider', required
  - `type` 'action' | 'interaction' | 'llm_response', required
  - `user_id` string, nullable
  - `agent_variant_id` string, nullable
  - `version_hash` string, nullable

## Response `200`

Successful Response

- EventPublicWithChildren: Adds the polymorphic children so the response carries whichever child (interaction / action / llm_response) matches the event type. The source ORM eager-loads all three (``lazy="selectin"`` on the relationships), so reading them during from_attributes serialization doesn't trip a lazy-load.
  - `id` string, required
  - `organization_id` string, required
  - `engagement_id` string, required
  - `origin` 'internal' | 'external', required
  - `role` 'user' | 'agent' | 'contact' | 'provider', required
  - `type` 'action' | 'interaction' | 'llm_response', required
  - `user_id` string, nullable
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `deleted_at` string, date-time, nullable
  - `interaction` EventInteractionPublic
    - `id` string, required
    - `channel_id` string, required
    - `contact_method_id` string, nullable
    - `image_id` string, nullable
    - `external_id` string, nullable
    - `twilio_message_status` string, nullable
    - `twilio_error_code` string, nullable
    - `telnyx_message_status` string, nullable
    - `telnyx_error_code` string, nullable
    - `metadata_json` object, nullable
    - `status` 'pending' | 'delivered' | 'received' | 'failed', required
    - `content` string, required
    - `translated_content` string, nullable
    - `deliver_after` string, date-time, nullable
  - `action` EventActionPublic
    - `id` string, required
    - `tool_module_id` string, required
    - `success` boolean, nullable
    - `type` 'booking' | 'booking_request'
    - `invocation_source` 'llm' | 'precall': Who invoked the tool that produced this action. ``LLM`` — the agent's model chose to call the tool mid-conversation. ``PRECALL`` — the system/operator ran the tool up front (before-turn hooks / pre-agent preload) and injected the result into the prompt; the model did not choose it. ``NULL`` means **legacy / unknown** — the row predates reliable tagging (ENG-4234) and is NOT necessarily LLM-invoked. Precalled tools were saved as actions before #4213 (2026-04-04), then not saved at all until ENG-4234, so historical rows are a mix we deliberately don't reconstruct. Readers must treat NULL as its own bucket, never fold it into ``LLM``. Only rows written after ENG-4234 shipped carry a trustworthy value.
    - `input` string, required
    - `output` string, required
  - `llm_response` EventLLMResponsePublic
    - `id` string, required
    - `phase` 'ModelRequest' | 'ModelResponse', required: Phase for persisted LLM transcript rows. Like other engagement ``StrEnum`` + ``sa.Enum(native_enum=False)`` columns, PostgreSQL stores the member **name** (``REQUEST`` / ``RESPONSE``) for ``llmphase``. The **value** strings are pydantic-ai message kinds (``ModelRequest`` / ``ModelResponse``) and are not written to this column.
    - `model` string, required
    - `content` union
      - object
      - unknown[]
        - unknown
      - string
    - `duration_ms` integer, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/upsmith/apis/upsmith-api.md) - [All operations](https://skmtc.dev/upsmith/apis/upsmith-api/llms.txt) - [OpenAPI document](https://skmtc.dev/upsmith/apis/upsmith-api/revisions/cce8b07a5787?raw)
