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

# Sync Explorer console: read, write, and publish shared state from the dashboard

> Use the Sync Explorer at /developer/sync to fetch Documents, Maps, and Lists by unique_name, read their current revision, apply create/update/delete operations, and publish Stream messages — all without leaving the dashboard.

The Sync Explorer is a dashboard operator console that surfaces the same
durable shared-state primitives the [Sync REST surface](/guides/sync-realtime-state)
exposes — Documents, Maps, Lists, and Streams — through a set of per-kind forms.
Read the [Sync end-to-end guide](/guides/sync-realtime-state) for the object
model, REST endpoints, and WebSocket protocol; this page covers the dashboard
console: where it lives, what each tab does, one worked example per kind, and
the failure modes you can hit.

## 1. Where the explorer lives

Open the dashboard, choose **Developer** in the sidebar, and select **Sync
Explorer** from the tile grid (or navigate directly to `/developer/sync`). The
page is available to owners, admins, and developer roles — the same roles that
hold write permission on the Sync REST surface.

The explorer is a thin shell over four per-kind tabs:

| Tab | Icon | What you do |
| - | - | - |
| Documents | `FileJson` | Fetch a single JSON object by `unique_name`, read its revision, and apply create / update / delete. |
| Maps | `MapIcon` | Load a key → JSON-value collection, list every item with its revision, set or remove individual items, and delete the entire map. |
| Lists | `ListIcon` | Load an ordered zero-based list, list every item with its index and revision, append new items, set at an index, remove at an index, and delete the entire list. |
| Streams | `Radio` | Publish one ephemeral pub/sub message; nothing is stored and nothing is fetched. |

## 2. Reading a Sync object

Every durable kind — Documents, Maps, and Lists — is fetched by its
`unique_name`. Type the name into the field at the top of the tab and click
**Load**. The explorer calls the same `GET` endpoints a client application
would use, and the response renders in the card below:

* **Documents** — the current JSON `data` plus `revision` and `date_updated`.
* **Maps** — every key with its `data` and per-item `revision`.
* **Lists** — every item with its zero-based `index`, `data`, and `revision`.

If the object does not exist (or its TTL expired) you see an empty state
prompt instead of an error — the forms below let you create it.

**Streams have no read surface.** A Stream is ephemeral — a message fans out
to subscribers connected at publish time and nothing is stored. There is no
**Load** button on the Streams tab and nothing to fetch.

## 3. Mutating objects

Below the read card, a data editor lets you compose a JSON object. The editor
validates parse on every keystroke and disables the action buttons until the
JSON is valid.

| Operation | Tab | Button | Effect |
| - | - | - | - |
| Create | Documents | **Create** | `POST /documents` with the `unique_name` and editor data. Fails with a conflict if the name already exists. |
| Update | Documents | **Update loaded** | Overwrites the loaded Document's data. Revision is managed server-side — the explorer reads, then writes, so a stale-write race is possible (see failure modes). |
| Set item | Maps | **Set item** | `PUT /maps/:name/items/:key` — create or replace the value at that key. |
| Delete item | Maps | Trash icon per item | `DELETE /maps/:name/items/:key` — remove one key from the map. |
| Delete map | Maps | **Delete map** | `DELETE /maps/:name` — removes every item and the map itself. |
| Append | Lists | **Append** | `POST /lists/:name/items` — adds one item at the next index. |
| Set at index | Lists | **Set at index** | `PUT /lists/:name/items/:index` — overwrite the value at a specific zero-based index. |
| Delete item | Lists | Trash icon per item | `DELETE /lists/:name/items/:index` — remove the item at that index. |
| Delete list | Lists | **Delete list** | `DELETE /lists/:name` — removes every item and the list itself. |

Every destructive action prompts a confirmation dialog before the request is
sent.

### Revision and CAS

Documents and List/Map items carry a monotonic `revision` the explorer
displays. On an **Update loaded** the explorer sends the form data without an
explicit revision guard — the server compares revisions internally and returns
a 409 if another writer changed the object since you loaded it (see the
failure modes section below).

## 4. Publishing to a Stream

The Streams tab has a single form: a `unique_name`, a JSON editor, and a
**Publish message** button. Clicking it sends `POST
/streams/:name/messages` with your data. The message fan-out is immediate
and fire-and-forget — the explorer does not show a receipt or subscriber
count. Subscribers connected over the WebSocket gateway at publish time
receive the `stream.message` event; clients that connect later never see it.

## 5. Per-kind worked examples

Each example below is a concrete pair you can type into the explorer right now
and observe the result.

### Document: presence state

**Tab:** Documents. **Name:** `agent_presence`. **Data:**

```json theme={null}
{
  "agent_id": "agent_7",
  "status": "available",
  "last_heartbeat": "2026-10-08T12:00:00Z"
}
```

Click **Create**. The card renders the stored JSON with revision `1`. Change
the status to `busy`, click **Update loaded**, and revision ticks to `2`.

### Map: order details

**Tab:** Maps. **Name:** `order_4982`. **Key:** `shipping`. **Data:**

```json theme={null}
{
  "carrier": "DHL",
  "tracking": "1234567890",
  "eta": "2026-10-12"
}
```

Click **Set item**. Add another key (`billing`) with different data. The card
lists both keys with their individual revisions.

### List: audit trail

**Tab:** Lists. **Name:** `queue_audit`. **Data:**

```json theme={null}
{ "actor": "operator_3", "action": "escalated", "ticket": "TKT-442" }
```

Click **Append**. Repeat with a second entry. The card lists both items at
indices `[0]` and `[1]`.

### Stream: live counter

**Tab:** Streams. **Name:** `metrics_dashboard`. **Data:**

```json theme={null}
{ "active_calls": 12, "waiting": 3 }
```

Click **Publish message**. The message is sent. A subscribing client receives
the envelope; the explorer stays silent.

## 6. When to use the explorer vs the REST surface

The [Sync end-to-end guide](/guides/sync-realtime-state) covers the full REST
API — `curl` commands, error codes, the WebSocket gateway, and the
programmable integration path. Choose the right surface by who is acting:

* **Explorer** — a human operator inspecting state, debugging a presence
  roster, checking a document value, or sending a one-off Stream message from
  the dashboard. No code, no key management, and the same role gates as REST.
* **REST + WebSocket** — an application or backend worker that creates,
  reads, and reacts to Sync objects under application control. It holds an API
  key, handles retries and rate limits, and subscribes over the WebSocket
  gateway for live change events.

The explorer reads and writes the exact same objects — a document created
through the REST `POST /sync/documents` is immediately fetchable in the
explorer, and a Stream message published from the dashboard is delivered to
subscribing clients over the WebSocket gateway.

## 7. Failure modes

| Symptom | Cause | What to do |
| - | - | - |
| Empty state after **Load** | The `unique_name` does not exist, or its TTL expired. | Create the object with the form below, or shorten the TTL window on the write side so missing state is expected. |
| "Document not found" on a known-existing name | The name contains a character outside the allowed set (letters, digits, `.`, `_`, `:`, `-`) or exceeds 256 characters. | Choose a valid name and retry. |
| Stale update rejected | You loaded the object, another writer changed it, and the server returned a 409 revision conflict before your **Update loaded** landed. | Click **Load** again to re-hydrate the current state, then re-apply your edit. |
| **Create** disabled for a Document that does not exist | The name field is empty, or the JSON editor contains invalid JSON. | Fill the name and fix the parse error — the inline hint tells you what is wrong. |

TTL expiry applies to Documents and Maps (and Map items) that were created
with a non-zero `ttl`. Once the window elapses the object vanishes silently —
a subsequent **Load** shows the empty state. Streams have no TTL because they
have no retention.

## 8. See also

* [Sync real-time state end to end](/guides/sync-realtime-state) — the full
  REST surface, WebSocket gateway, TTL semantics, and error taxonomy
* [Developer console map](/guides/developer-hub-consoles) — every tile in the
  Developer hub on one page
* [Sync API reference](/api-reference/sync) — endpoint-by-endpoint shapes


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.