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

# Snapshot API

> Query the current state of joins and windows via HTTP for initial UI hydration.

# Snapshot API

The Snapshot API lets you query the current state of any join or window via a simple HTTP `GET` request. It solves the "cold start" problem: when a dashboard loads, it can fetch a snapshot of current results immediately instead of waiting for the next SSE event.

## Endpoint

```
GET /snapshot
```

Available on any SSE sink's HTTP server (the same address as `/subscribe`).

## Query Parameters

| Param   | Required | Default | Description                            |
| ------- | -------- | ------- | -------------------------------------- |
| `join`  | yes      | —       | Join or window name, or `*` for all.   |
| `from`  | no       | —       | Start time (RFC 3339 or Unix seconds). |
| `to`    | no       | now     | End time (RFC 3339 or Unix seconds).   |
| `limit` | no       | 10000   | Max rows per join/window.              |
| `keys`  | no       | —       | Comma-separated key filter.            |

## Examples

### Fetch all results

```bash theme={null}
curl http://localhost:9100/snapshot?join=* | jq
```

### Fetch a specific join

```bash theme={null}
curl http://localhost:9100/snapshot?join=order-user-join | jq
```

### Filter by keys

```bash theme={null}
curl "http://localhost:9100/snapshot?join=order-user-join&keys=order_123,order_456" | jq
```

### Time-range query

```bash theme={null}
curl "http://localhost:9100/snapshot?join=order-user-join&from=2026-02-22T00:00:00Z" | jq
```

## Response Format

The response is a JSON array of `JoinResult` objects — identical to SSE event payloads:

```json theme={null}
[
  {
    "query": "order-user-join",
    "key": "order_123",
    "rows": [
      {
        "order_id": "order_123",
        "amount": 45.00,
        "customer_name": "Alice"
      }
    ],
    "emit_at": "2026-02-22T10:00:00Z"
  }
]
```

### Status Codes

| Code  | Meaning                                 |
| ----- | --------------------------------------- |
| `200` | Success (may be an empty array)         |
| `400` | Invalid parameters                      |
| `500` | Query execution failed                  |
| `503` | Storage not ready (engine initializing) |

## Frontend Integration

### Snapshot + SSE Pattern

The recommended pattern is to fetch a snapshot for initial state, then open an SSE stream for live updates:

```javascript theme={null}
async function connect() {
  const baseUrl = 'http://localhost:9100';

  // Hydrate current state
  try {
    const res = await fetch(`${baseUrl}/snapshot?join=*`);
    const results = await res.json();
    for (const result of results) {
      handleJoinResult(result);
    }
  } catch (e) {
    console.warn('Snapshot failed, will populate from SSE:', e);
  }

  // Then open SSE for live updates
  const es = new EventSource(`${baseUrl}/subscribe?join=*`);
  es.addEventListener('join_result', (event) => {
    handleJoinResult(JSON.parse(event.data));
  });
}
```

### Replay Alternative

Instead of a separate fetch, add `?replay=true` to the SSE URL:

```javascript theme={null}
const es = new EventSource('http://localhost:9100/subscribe?join=*&replay=true');
```

With replay, the server emits current results as SSE events (with `"_replay": true`) before switching to live streaming. The `replay_complete` event signals when initial hydration is done:

```
event: join_result
data: {"query":"...", "_replay": true, ...}

event: replay_complete
data: {"join":"*","count":42}

event: join_result
data: {"query":"...", ...}   ← live from here
```

## Archive Queries

When the `from` parameter extends beyond the retention window (data has been compacted to Parquet), the snapshot handler automatically queries the [archive federator](/operations/storage) if tiered storage is enabled.

This means a single `/snapshot` request can transparently query data across:

* **Hot** SQLite (recent data)
* **Warm** local Parquet files (days old)
* **Cold** cloud Parquet files (weeks/months old)

## Configuration

The snapshot endpoint is enabled by default on any SSE sink. Optional tuning:

```yaml theme={null}
sinks:
  - name: dashboard
    type: sse
    config:
      addr: ":9100"
      snapshot:
        enabled: true
        default_limit: 10000
        timeout: 10s
        replay: true
```
