A data source is how your dashboard gets runtime data. Twinnoverse supports four data-source models, each suited for a different operating reality.
1. Types of Data Sources #
| Type | Best For | How It Works |
|---|---|---|
| REST API | Cloud APIs, MES/ERP services, existing web backends | The TV polls your API endpoint on a schedule |
| WebSocket | Realtime streams and low-latency updates | The TV keeps a persistent connection and receives pushed updates |
| Ingest | Local plant systems behind a firewall | A local gateway pushes data to Twinnoverse; the TV reads from the cloud snapshot |
| Manual | No API yet, operator-entered values | A user updates widget values manually from the Manual KPI screen |
Choose the source type based on how the data exists today, not on what you hope to build later. You can start with Manual, then move to REST, WebSocket, or Ingest when the integration is ready.
If you are not sure which path to use:
- choose REST API for normal polling from an existing backend
- choose WebSocket for pushed live updates
- choose Ingest for a local gateway inside the plant network
- choose Manual when people will enter the values directly
2. REST API Data Source #
The TV periodically calls your API endpoint to fetch fresh data.
Settings #
| Setting | Description |
|---|---|
| Name | A friendly name for this data source |
| Base URL | The full URL of your API endpoint, for example https://api.example.com/production |
| HTTP Method | GET or POST |
| Refresh Interval | How often the TV polls, in seconds |
| Headers | Optional HTTP headers such as API keys or auth tokens |
GET vs POST #
| Method | When to Use |
|---|---|
| GET | Simple fetch when no request body is needed |
| POST | When your backend needs context such as prodline_id, device_id, or layout_id |
When using POST, the TV can send runtime context such as:
{
"prodline_id": "CH1",
"prodlineID": "CH1",
"reader_prodline_id": "CH1",
"device_id": "device-xxx",
"reader_device_id": "device-xxx",
"layout_id": "layout-xxx",
"playlist_slice_sec": 10,
"playlist_remaining_sec": 10,
"layout_duration_sec": 10,
"timestamp": "2026-06-18T09:30:00Z"
}Depending on the runtime path, Twinnoverse can also include fields such as:
delivery_idevent_occurrence_idevent_idevent_keysubject_typesubject_idsubject_nameprod_line_indexplaylist_item_index
Expected Response Format #
Your API should return JSON grouped by widget type, then by widget label:
{
"kpi": {
"PROD_TOTAL": {
"title": "Total Production",
"value": 1247
}
},
"progress_bar": {
"SHIFT_TARGET": {
"current": 22,
"total": 100
}
},
"alerts_list": {
"ALERTS": {
"items": [
{ "time": "09:00", "count": 1, "label": "Alert 1", "severity": "warning" }
]
}
}
}The label in your payload must match the widget label in the layout(you can define this in the layout editor).
The exact widget object shape depends on the widget family. For the full payload contract by widget type, use Dashboard Widget Reference Guide.
3. WebSocket Data Source #
Use WebSocket when data should appear as soon as the backend publishes it.
Settings #
| Setting | Description |
|---|---|
| Name | A friendly name for this data source |
| WebSocket URL | The endpoint, for example wss://stream.example.com/data |
| Subscription Message | Optional JSON sent after connection |
| Message Mode | Replace or Merge |
Subscription Message #
You can use placeholders:
| Placeholder | Replaced With |
|---|---|
{{prodline_id}} | Current production line ID |
{{prodlines_json}} | JSON array of the device prodlines and active prodline |
{{device_id}} | Current TV device ID |
{{layout_id}} | Active layout ID |
{{layout_name}} | Active layout name |
Example:
{
"action": "subscribe",
"prodlines": "{{prodlines_json}}",
"device_id": "{{device_id}}",
"layout_id": "{{layout_id}}"
}Expected Server Message Format #
{
"prodline": "CH1",
"mode": "replace",
"payload": {
"kpi": {
"WIP": { "title": "WIP Inventory", "value": 42 }
}
}
}| Field | Required | Description |
|---|---|---|
prodline | Yes | Which production line the message belongs to |
mode | No | replace or merge; defaults to the data source setting |
payload | Yes | The widget data payload |
Important Notes #
- WebSocket data appears only after the server sends a message.
- The TV reconnects automatically if the connection drops.
- Use
mergeonly if your backend intentionally sends partial updates. - If the server does not send a production line field, the reader falls back to the active layout context.
4. Ingest Data Source #
Use Ingest when the source system is on a local network and cannot expose a public API.
When to Use Ingest #
- Your machine, PLC, or local server is inside the plant network
- The local system can make outbound HTTPS calls
- You want a secure, firewall-friendly bridge to Twinnoverse
How It Works #
- You create an Ingest data source in Twinnoverse.
- Twinnoverse generates an ingest endpoint and ingest token.
- Your local gateway posts snapshots to that endpoint.
- The TV polls the latest accepted snapshot from Twinnoverse.
Settings #
| Setting | Description |
|---|---|
| Name | A friendly name |
| Ingest Endpoint | The fixed cloud endpoint |
| Ingest Token | The secret used by the gateway |
| Refresh Config | Refreshes connection details in the admin UI |
| Rotate Key | Generates a new token |
| Revoke Key | Disables the current token immediately |
Gateway Sender Format #
Send:
POST /functions/v1/ingest-data-source
Authorization: Bearer <your_ingest_token>
Body:
{
"prodline_id": "CH1",
"payload": {
"kpi": {
"PROD_TOTAL": { "title": "Total", "value": 1247 }
}
},
"source_metadata": {
"source": "gateway-name"
}
}5. Manual Data Source #
Use Manual when you do not have an integration yet, or when the values must be entered by an operator, supervisor, or shift lead.
When Manual Is the Right Choice #
- You are launching quickly and the API is not ready
- The KPI values are typed in once per shift or once per hour
- The layout is shared by several TVs on the same production line
- Operators need direct control over alert text, counts, or status values
How Manual Works #
- Create a data source with type Manual.
- Assign that data source to a layout.
- Open Manual KPI from the admin shell.
- Select the production line and layout.
- Click widgets in the preview and enter their runtime values.
- Save the snapshot.
- All TVs using that layout for that production line show the same saved values.
Important Notes #
- Manual data is saved per layout + production line, not per device.
- Manual KPI changes runtime values only.
- Layout structure, colors, titles, and theme still come from the layout itself.
clockand runtime-context widgets are not edited through Manual KPI.
See Manual KPI for the full workflow.
6. Assigning a Data Source to a Layout #
- Create your layout with widgets.
- In the Layout Editor, deselect all widgets.
- In the Inspector, choose the Data Source for the layout.
- Save the layout.
- Add the layout to a playlist and assign that playlist to a device.
Each layout can use one data source at a time.
7. Data Source Health #
The TV taskbar and preview tools can show messages such as:
| Message | Meaning |
|---|---|
No data source assigned | The layout is not linked to any data source |
Data source not found | The linked data source was deleted |
Fetch error: ... | The data source returned an error and the TV will retry |
Last fetch: ... | The data source is working and reporting status normally |
8. Admin Preview and Data Sources #
Twinnoverse also includes an admin preview path so you can inspect what a device should display without standing in front of the TV.
Important points:
- the preview uses the same runtime rendering logic as the Reader
- the preview can show data-source-related messages and fetch status
- preview is useful for checking payload shape, layout binding, and screen output before testing on the physical TV
- preview helps validate REST, WebSocket, Ingest, and Manual flows from the admin side
Use preview to answer questions like:
- is the layout bound to the correct data source?
- does the payload shape match the widget labels?
- is the device expected to show data or an error state?
Preview is a validation tool. The physical TV is still the final runtime target.
9. Best Practices #
Do #
- Use REST for straightforward polling integrations
- Use WebSocket only when realtime push is truly needed
- Use Ingest when the source lives inside the factory network
- Use Manual when the data is operator-entered or no API exists yet
- Keep widget labels stable after you bind integrations
Avoid #
- Polling too aggressively
- Mixing manual and API expectations for the same layout without a clear process
- Deleting a data source that is still attached to active layouts
