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

# Event types

Every asset event Motioness emits via SSE and webhooks.

# Event types

Closed enum. New event types in future versions are additive — existing types never change shape.

## Lifecycle events

| Event | Stage | Notes |
|---|---|---|
| `queued` | — | Asset row inserted, work accepted |
| `vision_started` | vision | Claude vision call dispatched |
| `vision_completed` | vision | Vision returned a motion prompt |
| `vision_failed` | vision | Vision rejected the source |
| `stage_started` | stage1/stage2/merge/single | Replicate prediction submitted |
| `stage_completed` | stage1/stage2/merge/single | Prediction returned mp4 |
| `stage_failed` | stage1/stage2/merge/single | Prediction errored or timed out |
| `retry_scheduled` | any | Transient error, retry queued (observational) |
| `r2_write_completed` | — | mp4 stored in R2 |
| `ready` | — | Terminal success |
| `failed` | — | Terminal failure (`error_code` field) |
| `cancelled` | — | Manual cancel via dashboard |

## Webhook delivery events

These fire only when webhooks are enabled on the project:

| Event | Notes |
|---|---|
| `webhook_dispatched` | Outbound delivery enqueued |
| `webhook_delivered` | Customer endpoint responded 2xx |
| `webhook_failed` | Endpoint errored or timed out (will retry) |
| `webhook_dead_letter` | 5 failed attempts, won't retry automatically |

## Common fields

Every event carries:

```ts
type AssetEvent = {
  ts: number;            // unix ms
  attempt: number;       // 1-based, increments on retries
  request_id: string;
  asset_id: string;
  project_id: string;
  // type-specific extras:
  stage?: 'stage1' | 'stage2' | 'merge' | 'single' | 'vision' | 'r2_write';
  latency_ms?: number;   // on *_completed
  error_code?: string;   // on *_failed
  error_msg?: string;    // on *_failed
};
```

## `error_code` enum

`error_code` is the stable identifier on `*_failed` events. Branch on this, not on `error_msg`.

```text
vision_blocked        — source rejected (NSFW, copyright, oversize)
vision_timeout        — vision exceeded 30s
source_unfetchable    — 4xx/5xx fetching source URL
source_too_large      — source > 10 MB
source_unsupported    — non-png/jpg/webp content-type
i2v_failed            — image-to-video model errored
i2v_timeout           — i2v exceeded 5 min
merge_failed          — loop stitching failed
r2_write_failed       — R2 write errored (auto-retried; rare)
quota_exceeded        — monthly limit hit mid-flight
pipeline_stalled      — cron reconciler gave up after 10 min
```

## SSE format

```text
id: 1714801234567
event: stage_completed
data: {"stage":"stage1","latency_ms":4820,"asset_id":"a25b…","ts":1714801234567}
```

## Webhook envelope

```json
{
  "id": "evt_01HXY3K…",
  "type": "asset.completed",
  "ts": 1714801234567,
  "asset_id": "a25b…",
  "project_id": "proj_abc",
  "request_id": "req_xyz",
  "data": { /* event-specific payload */ }
}
```

The `type` field on webhooks is namespaced as `asset.<eventType>` (e.g. `asset.completed`, `asset.failed`). SSE events use the bare event type.

## Subscribing

| Channel | Auth | Endpoint |
|---|---|---|
| SSE (public) | Project key | `GET /v1/{key}/events/{asset_id}` |
| SSE (auth-gated, per-asset) | Session cookie | `GET /api/assets/{id}/events` |
| SSE (auth-gated, project-wide) | Session cookie | `GET /api/projects/{id}/activity` |
| Webhooks | Outbound HMAC-signed POST | Configure via `PUT /api/projects/{id}/webhooks` |