# Web Form Progress Events — Example Payload

Example JSON payload the SPA sends to `POST /api/public/v1/web-form-events`, based on the
validation rules in `App\Http\Requests\PublicApi\WebFormEventStoreRequest`.

```json
{
  "session_id": "9c3e6a2e-2f2b-4c9a-8e2a-1a2b3c4d5e6f",
  "events": [
    {
      "type": "field_focus",
      "field": "email",
      "sequence": 1,
      "at": "2026-07-28T18:32:01.123Z"
    },
    {
      "type": "field_blur",
      "field": "email",
      "sequence": 2,
      "meta": { "value": "jane@example.com" },
      "at": "2026-07-28T18:32:04.987Z"
    },
    {
      "type": "field_change",
      "field": "primary_account_identifier",
      "sequence": 3,
      "meta": { "value": "1234567890123" },
      "at": "2026-07-28T18:32:10.442Z"
    },
    {
      "type": "step_complete",
      "field": null,
      "sequence": 4,
      "meta": { "step": "contact_info" },
      "at": "2026-07-28T18:32:11.005Z"
    }
  ]
}
```

## Field notes

- `session_id` — required UUID, taken verbatim from `data.session_id` in the
  `GET /web-forms/{identifier}` response.
- `events` — required array, 1–50 items per batch (the SPA should buffer/debounce and flush
  periodically or on field blur/step change).
- `events[].type` — required string, ≤64 chars; free-form event name (`field_focus`,
  `field_blur`, `field_change`, `step_complete`, etc. — the app doesn't enforce an enum, so the
  SPA and any downstream analysis need to agree on a vocabulary).
- `events[].field` — optional, the form field name this event pertains to.
- `events[].sequence` — optional integer, useful for ordering events within a session.
- `events[].meta` — optional object; can include entered field values (per the decision to allow
  this), step names, validation state, etc.
- `events[].at` — optional client-side ISO 8601 timestamp; if omitted, the server stamps
  `occurred_at` with its own `now()`.

## Response

Successful response is `202` with:

```json
{
  "data": {
    "recorded": 4
  }
}
```
