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

# Push Structured Widget Data

> Replace a Structured Widget snapshot securely through the Layarva Push API.

## What you'll accomplish

You will activate a Structured Widget Push source, authenticate a server-to-server request, replace the current snapshot, and implement safe retries.

## Supported Widgets

Structured Push v2 currently supports these exact mappings:

| Studio Widget       | `widgetType`      |
| ------------------- | ----------------- |
| Announcements       | `ANNOUNCEMENTS`   |
| Today's Schedule    | `TODAYS_SCHEDULE` |
| Events              | `EVENTS`          |
| Departure & Arrival | `TRANSPORT_BOARD` |

## Endpoint

```http theme={null}
POST https://app.layarva.com/api/public/v1/widgets/{widgetId}/data/push
```

The API accepts a complete replacement snapshot. Partial patches are not supported.

## Prerequisites

* A supported Widget added to a Design.
* Content editing permission to activate its Push source.
* The Widget's **Unique Widget ID**.
* An active Workspace API Key stored in a trusted backend or automation.

## Get the Widget ID and API key

1. Select the Widget in Studio Canvas.
2. Open **Properties → Data Source**.
3. Select **Layarva Push API**.
4. Open **API Setup & Usage Guide**.
5. Copy the Unique Widget ID and the one-time full Workspace API Key.
6. Save and publish the Design once.

The full key cannot be displayed again. Rotate it if the value is lost or exposed.

## Authenticate the request

```http theme={null}
Authorization: Bearer <workspace-api-key>
Content-Type: application/json
Idempotency-Key: agenda-20260827-revision-001
```

`Authorization: Bearer` is recommended. The route also accepts `x-layarva-api-key` for server integrations. Do not send both.

## Send a schedule snapshot

```bash theme={null}
curl -X POST \
  "https://app.layarva.com/api/public/v1/widgets/<WIDGET_ID>/data/push" \
  -H "Authorization: Bearer <WORKSPACE_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: agenda-20260827-revision-001" \
  --data-binary @- <<'JSON'
{
  "pushVersion": 1,
  "widgetType": "TODAYS_SCHEDULE",
  "writeMode": "REPLACE_SNAPSHOT",
  "source": {
    "eventId": "cms-agenda-sync-20260827-001",
    "sequence": 101,
    "generatedAt": "2026-08-27T08:00:00+07:00"
  },
  "data": {
    "schemaVersion": 2,
    "title": "Today's Agenda",
    "subtitle": "Main meeting room",
    "locale": "en-US",
    "timezone": "Asia/Jakarta",
    "date": "2026-08-27",
    "updatedAt": "2026-08-27T08:00:00+07:00",
    "items": [
      {
        "id": "agenda-001",
        "startAt": "2026-08-27T09:00:00+07:00",
        "endAt": "2026-08-27T09:30:00+07:00",
        "title": "Morning Briefing",
        "location": "Meeting Room A",
        "host": "Operations",
        "status": "SCHEDULED"
      }
    ]
  }
}
JSON
```

## Understand the request envelope

| Field                | Required    | Rule                                                           |
| -------------------- | ----------- | -------------------------------------------------------------- |
| `pushVersion`        | Yes         | Integer `1`                                                    |
| `widgetType`         | Yes         | Must match the target Widget                                   |
| `writeMode`          | Yes         | Must be `REPLACE_SNAPSHOT`                                     |
| `source.eventId`     | No          | Source-system event identity for audit                         |
| `source.sequence`    | Recommended | Non-negative safe integer that increases for each new snapshot |
| `source.generatedAt` | Recommended | ISO 8601 timestamp with an offset                              |
| `data`               | Yes         | Strict semantic Widget payload with `schemaVersion: 2`         |

Unknown envelope and payload fields are rejected. HTML markup is not accepted in semantic text fields.

## Successful response

```json theme={null}
{
  "accepted": true,
  "widgetId": "wdg_example",
  "widgetType": "TODAYS_SCHEDULE",
  "dataRevision": 12,
  "schemaVersion": 2,
  "acceptedAt": "2026-08-27T01:00:01.125Z",
  "itemCount": 1,
  "warnings": []
}
```

The response also includes `X-Layarva-Data-Revision`. Record the revision with the source event in your integration logs.

## Implement idempotency and ordering

* `Idempotency-Key` is optional but strongly recommended for every logical snapshot.
* A key contains 8–180 characters and is retained for 24 hours.
* Retrying the same key with the same raw body returns the original response.
* Reusing the key with a different raw body returns HTTP 409 `IDEMPOTENCY_KEY_REUSED`.
* When `source.sequence` is present, it must be greater than the last accepted sequence.
* An equal or lower sequence returns HTTP 409 `STALE_SOURCE_SEQUENCE`.

Keep the serialized body unchanged during an idempotent retry. Even harmless whitespace changes produce a different request hash.

## Request limits

* Maximum body size: 1 MiB.
* Default rate limit: 120 Push attempts per Widget in a rolling one-minute window.
* `Content-Type` must include `application/json`.
* Schedule and Event arrays accept up to 500 items.
* Announcement arrays accept up to 200 items.
* Transport arrays accept up to 1,000 items.

## Handle errors

| HTTP | Representative code                                   | Action                                                  |
| ---- | ----------------------------------------------------- | ------------------------------------------------------- |
| 400  | `INVALID_JSON`, `INVALID_IDEMPOTENCY_KEY`             | Correct the JSON or header                              |
| 401  | `AUTHENTICATION_REQUIRED`                             | Supply a Workspace API Key                              |
| 403  | `WIDGET_NOT_FOUND_OR_FORBIDDEN`                       | Verify the key, workspace, active source, and Widget ID |
| 409  | `IDEMPOTENCY_KEY_REUSED`, `STALE_SOURCE_SEQUENCE`     | Preserve the original retry body or increase sequence   |
| 413  | `PAYLOAD_TOO_LARGE`                                   | Reduce the snapshot below 1 MiB                         |
| 415  | `UNSUPPORTED_CONTENT_TYPE`                            | Send `application/json`                                 |
| 422  | `SCHEMA_VALIDATION_FAILED`, `UNSUPPORTED_WIDGET_TYPE` | Correct the envelope or semantic payload                |
| 429  | `RATE_LIMITED`                                        | Back off for at least one minute with jitter            |

Do not retry schema, authentication, or conflict errors blindly. Retry HTTP 429 and transient server failures with exponential backoff, preserving the Idempotency Key and body for the same logical snapshot.

## Validate the integration

1. Send the first snapshot and require `accepted: true`.
2. Record its `dataRevision`.
3. Confirm the Player changes after the configured Widget refresh interval.
4. Retry the identical request and confirm the revision does not increase.
5. Send a new body with a new Idempotency Key and higher sequence.
6. Confirm the Widget changes without republishing the Design.
7. Test invalid schema, stale sequence, expired key, rate limit, and temporary network failure behavior.

## Important notes

* This endpoint is not a general API for editing Designs, Playlists, Screens, or Publications.
* The Push API changes the Widget's semantic data, not its layout or visual style.
* Legacy Widget integration dialogs can use a different endpoint and body. Use the request generated by that Widget's Studio dialog.
* Keep Static JSON valid so the Player has a safe fallback before the first accepted dynamic snapshot.

## Related guides

* [Connect Data to a Widget](/studio/widget-data-sources)
* [Build a Widget WebSocket Relay](/developers/widget-websocket)
* [Handle API Errors](/developers/error-codes)
* [API Rate Limits](/developers/rate-limits)
