---
title: "Create Event"
method: POST
path: "/events/{stream_id}"
tags: ["events"]
---

# Create Event

`POST /events/{stream_id}`

## Request

- Base URL: `https://api.verdun.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.verdun.ai/events/{stream_id}`
- Auth: API key in header `X-API-Key`

## Path parameters

- `stream_id` string, required

## Request body

- CreateEventRequest
  - `zone` string, required: Zone code
  - `clip_s3_url` string, required: S3 URL
  - `summary` string, nullable: Mapped summary column
  - `motion_score` string, nullable: Mapped motion score column
  - `source` string, nullable: Mapped source column
  - `detection_mode` string, nullable: The ingestor runner's detection_mode snapshot for this clip; when present it overrides the live camera row for the response's routing fields. Normalized to lowercase; values outside {legacy, ii_gated} degrade to None (camera-row fallback) rather than rejecting the alarm write
  - `occurred_at` string, date-time, nullable: When the motion actually started (clip trigger time). The schedule gate is evaluated at this instant so clip-upload latency at an hour boundary can't misclassify the event. Absent = evaluated at receipt time.
  - `camera_id` string, nullable: The ingestor runner's own api camera id for this stream, captured once at the processor's construction. When present, create_event 409s if it disagrees with the camera actually resolved by kvs_stream_name. Malformed values degrade to None (the check is skipped) rather than rejecting the alarm write.

## Response `200`

Successful Response

- CreateEventResponse
  - `id` string, uuid, required: UUID of event
  - `kvs_stream_name` string, required: KVS stream name
  - `zone` string, required: Zone code
  - `clip_s3_url` string, required: S3 URL
  - `summary` string, nullable: Mapped summary column
  - `motion_score` number, nullable: Mapped motion score column
  - `source` string, nullable: Mapped source column
  - `parent_id` string, uuid, required: Tenant ID
  - `camera_id` string, uuid, required: Camera ID
  - `site_id` string, uuid, required: Site ID
  - `rag_context` string, nullable: Camera scene context for the LLM prompt
  - `site_timezone` string, nullable: IANA timezone of the site
  - `event_local_time` string, nullable: Event time in the site's local timezone (ISO 8601)
  - `monitoring_state` string, nullable: Schedule mode at the event time: 'monitored' or 'heightened' ('off' events are suppressed)
  - `heightened_exceptions` string, nullable: JSON-encoded exception list; null outside heightened windows
  - `ignore_zones` string, nullable: JSON-encoded ignore=true masking polygons (points only, percent 0-100 of the frame) for the AI pipeline to redact before analysis; null when the camera has none
  - `monitoring_profile` string, nullable: The camera's monitoring profile: 'security' (intrusion/theft/robbery) or 'safety' (slips/falls/person-down)
  - `detection_mode` string, nullable: Camera's DeepAlert routing state: 'legacy' | 'ii_gated'; null means legacy
  - `deepalert_sensor_id` string, nullable: Provisioned DeepAlert sensor id; populated only when detection_mode == 'ii_gated'
  - `deepalert_confidence_threshold` number, nullable: The DeepAlert confidence floor (0-100, lower = more sensitive) in force for this event: the camera's valid override, else the fleet default. On the ii_gated path it is always a number (null only for a corrupt persisted tuple, which ii stamps ii_fail_safe); null off the ii_gated path. Persisted per event and returned unchanged on a dedupe retry
  - `deepalert_confidence_threshold_source` string, nullable: Where that value came from: 'camera' (a valid per-camera override) | 'fleet_default' | 'invalid_override' (the stored override was unusable; the fleet default applied). Null off the ii_gated path. Old ingestors drop this key; ii then stamps the provenance 'unknown'
  - `deepalert_confidence_threshold_revision` integer, nullable: The fleet-default revision the value was resolved under (the epoch key; see PUT /settings/deepalert-default-confidence-threshold). Null off the ii_gated path
  - `deepalert_classes` string, nullable: Owner-configured DeepAlert classes as a canonical comma-joined string ('people' | 'vehicles' | 'people,vehicles'); null means both. Populated only when detection_mode == 'ii_gated'
  - `fire_watch` boolean, nullable: Whether the fire-screen fallback should run for this camera's gate-negative clips
  - `display_rotation` integer: The camera's display rotation (degrees CCW, 0 or 180) that ignore_zones is expressed against. The ingestor compares it with the rotation it stamped on the clip and transforms ignore_zones into the clip's space on a mismatch. 0 = no rotation or an api that predates the field.
  - `deduplicated` boolean: True when this response describes an existing event (a retry of an already-successful create), not a new insert

## Other responses

- `422`: Validation Error

---

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