Dynamic Ingest API
Update a dynamic feed with a write key (HTTP) or through MCP (OAuth). Exactly one layout arm: a saved layout, or UI on Demand.
Two ways to send an update
- HTTP write key —
POST https://glance-api.fly.dev/ingest/{feed_id}withAuthorization: Bearer {write_key}. For your backend, Shortcuts, Zapier, Make, or n8n. - MCP ingest tool — ChatGPT, Claude, or Cursor call
ingestwith the user's Glance OAuth token. No write key. See Glance MCP.
Find the feed ID and write key on the feed detail page in the iOS app or web console. The write key is shown once when a widget is created. Keep it secret. MCP hosts must not ask for it.
Layout XOR
Every dynamic ingest sends content plus exactly one layout arm. Never both. Top-level tree is the same arm as inline_ui.tree — do not send both.
| Arm | When | Content |
|---|---|---|
| template_id | Saved layout. Default. Recipes, automations, reuse. Available on every plan. | Merges with the previous snapshot |
| inline_ui | UI on Demand. Chrome travels with the data. Pro and Power. Does not create a layout row. | Full replace |
Same ingest URL for both. Same rate limits. See Features · Layout for the product words.
Saved layout
POST https://glance-api.fly.dev/ingest/{feed_id}
Authorization: Bearer {write_key}
Content-Type: application/json{
"schema_type": "dynamic",
"template_id": "YOUR_UI_TEMPLATE_UUID",
"content": {
"revenue": 12450,
"headline": "Today's revenue"
},
"metadata": {
"source": "my-backend"
},
"intent": {
"update_widget": true,
"send_push": false
}
}- template_id — UUID of the layout attached to the feed.
- content — object keyed by binding names from the derived schema (without
{{ }}wrappers). - intent — optional; controls widget update and push behavior (same as legacy feeds).
UI on Demand
Send the tree with the update when the Home Screen chrome should change with the task. Glance validates the tree the same way as create_template. It does not save a layout and does not spend a layout slot.
{
"schema_type": "dynamic",
"inline_ui": {
"tree": {
"id": "root",
"type": "container",
"layout": "vertical",
"style": { "padding": 12, "spacing": 8 },
"children": [
{
"id": "label",
"type": "text",
"binding": "Today's revenue",
"style": { "fontSize": 12, "color": "#8E8E93", "maxLines": 1 }
},
{
"id": "value",
"type": "stat",
"value": "{{revenue}}",
"style": { "valueFontSize": 28 }
}
]
},
"widget_size": "small"
},
"content": {
"revenue": 12450
}
}- inline_ui.tree — the home layout tree (v1 or v2). See Layout Language.
- inline_ui.views — optional named screens. Same map as
create_template. Needsfamily_views. Discover tiles still show home. - inline_ui.widget_size — optional. Must match the pinned widget slot if sent.
- content — binding names from this tree, not from a previous layout.
- Tree + views JSON must be 64 KiB or smaller. Resend the full tree on every update — there is no content-only follow-up shape.
contentmay include arrays andevent[]when the tree asked for them.
When not to use UI on Demand
- Free plan — create a layout and ingest with
template_id. Host Plus is not Glance Pro. Callget_planon MCP before promising this path. - Enabled automations — Glance-pull cron owns a saved layout. Disable the automation or use
template_id. - A face you want to reuse — save a layout. UI on Demand does not appear in Layouts and is not a cloneable template.
Public and Discover widgets may use UI on Demand. Subscribers see the owner's last push. On an older Glance app, that one slot can go blank until they update. Other widgets stay up.
Validation
Glance checks content against the layout's derived schema (saved layout) or against the tree in this request (UI on Demand). Missing required fields or wrong types return 400. Structural tree errors block the request. Design warnings (padding, overflow) do not. See Upload Content for field types.
- Both layout arms, or neither — 400
- UI on Demand on Free — 403, Pro required
- Chart, grid, table, or views on a plan without that family — 403
PREMIUM_FAMILY_REQUIRED - UI on Demand on a feed with an enabled automation — 400, use
template_id
Legacy schema ingest (Summary, Status, …) uses a different payload shape. See Legacy Webhook API.