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

# Issue kiosk realtime token

> Mint a short-lived JWT so a linked tablet can subscribe to device commands and workspace menu events.

Issues a 5-minute JWT signed with the project JWT secret. The token is `role: anon` with workspace claims (`merchant_id`, `env`) plus `device_uid`. Use it with the publishable key in the same payload to join the private device topic and the workspace topic.

> [!NOTE]
>
> Authenticates with `device_uid` and `device_secret` in the JSON body. This is
> not the customer [realtime
> token](https://firespark.cloud/docs/storefront-api/realtime/token/post.md).

Refresh before `expires_in`. The SDK helper `listenKiosk` refreshes about every 270 seconds.

## Request body

| Field | Required | Type | Description |
| - | - | - | - |
| `device_uid` | Yes | string | UUID from the link response. |
| `device_secret` | Yes | string | Bound tablet secret. |

## Request

```bash theme={null}
curl -X POST "https://firespark.cloud/api/storefront/v1/kiosk/realtime/token" \
  -H "Content-Type: application/json" \
  -d '{"device_uid":"7c8a1e2b-4d3f-4a91-9c2e-1f0b6a7d8e90","device_secret":"ksec_9f86d081884c7d659a2feaa0c55ad015"}'
```

## Response

The body is `{ data: KioskRealtimeToken }`.

| Field | Description |
| - | - |
| `access_token` | Short-lived JWT for `setAuth` on the Realtime client. Expires in 300 seconds. |
| `expires_in` | Always `300`. |
| `url` | Supabase project URL. |
| `key` | Publishable key. Safe to embed; RLS and the short token limit access. |
| `topic` | Device channel `sf:{merchant}:{env}:k:{device_uid}`. |
| `workspace_topic` | Workspace channel `sf:{merchant}:{env}` for menu and availability. |

## Events

Subscribe to `topic` for device events. Subscribe to `workspace_topic` for catalog events (same payloads as the [customer realtime token](https://firespark.cloud/docs/storefront-api/realtime/token/post.md)). For each CMS block the tablet renders, subscribe to `{workspace_topic}:cms:{block_name}`. Only devices joined to that block's topic receive its changes.

| Event | Topic | When |
| - | - | - |
| `kiosk.config.changed` | `topic` | Dashboard saved overrides or channel settings that affect this device. Payload `{ device_uid }`. |
| `kiosk.command` | `topic` | Remote command: `refresh_cache`, `reload`, or `unlink`. Payload `{ type, device_uid? }`. |
| `menu.changed` | `workspace_topic` | A menu sync finished as latest. Ignore events whose scope does not overlap this tablet. |
| `availability.changed` | `workspace_topic` | Availability or release rules were saved. Payload `{ merchant_id }`. |
| `payments.changed` | `workspace_topic` | A payment method was created, edited, or deleted. Payload `{ merchant_id }`. Refetch payments. |
| `fulfillments.changed` | `workspace_topic` | A fulfillment was created, edited, or deleted. Payload `{ merchant_id }`. Refetch fulfillments. |
| `cms.changed` | `{workspace_topic}:cms:{block_name}` | That CMS block was created, edited, renamed, or deleted. Payload `{ name }`. Refetch the block. |

## Errors

| Status | When |
| - | - |
| `404` | Device is missing or not `LINKED`/`ENROLLED`. `code: "DEVICE_NOT_LINKED"`. |
| `401` | Secret is not bound yet, or it does not match. |
| `400` | Body failed validation. |


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