Documentation
Learn how to integrate Glance into your workflows and display real-time data on your mobile devices.
Quick Start
- Create a Feed: Go to your dashboard and click "Create Feed"
- Choose a Schema: Select the type of data you want to display (Summary, Status, Counter, or Approval)
- Get Your Webhook URL: Copy the webhook URL and write key from the dialog
- Send Data: Make HTTP POST requests to your webhook URL with your data
- Add to Home Screen: Install the Glance iOS app and add widgets to your home screen
Authentication
All webhook requests must include your feed's write key in the Authorization header as a Bearer token.
curl -X POST "https://glance-api.fly.dev/ingest/YOUR_FEED_ID" \
-H "Authorization: Bearer YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{ ... }'Security: Keep your write keys secret! Never commit them to public repositories or share them publicly.
Intent Parameters
The intent object controls how Glance processes your webhook event. Use these parameters to fine-tune widget updates and push notification behavior.
update_widget
Type: boolean (optional, default: true)
When true, the widget on the user's home screen will update with the new data. When false, the event is logged but the widget display remains unchanged.
Use case: Set to false when logging events for analytics without changing the widget display, or when you want to send a push notification without updating the widget.
send_push
Type: boolean (optional, default: false)
When true, a push notification will be sent to the user's device with the event data. The notification respects user-configured quiet hours.
Use case: Enable for critical alerts (errors, deployments) or important updates. Keep disabled for frequent updates to avoid notification fatigue.
Best Practice: Use send_push: true sparingly to avoid overwhelming users. Reserve push notifications for actionable or time-sensitive information.
Example: Update Widget Without Push
{
"schema_type": "status",
"content": {
"title": "API Status",
"status": "success",
"message": "All systems operational"
},
"intent": {
"update_widget": true,
"send_push": false // Widget updates silently
}
}Example: Critical Alert with Push
{
"schema_type": "status",
"content": {
"title": "Production API",
"status": "error",
"message": "Database connection failed",
"details": "Last error: Connection timeout after 30s"
},
"intent": {
"update_widget": true,
"send_push": true // Sends immediate notification
}
}Summary Schema
Display a title with primary and optional secondary values. Perfect for metrics like revenue, account balances, or any key-value data.
Use Cases
- Daily/Monthly Revenue (e.g., "$12,345" with "+15%" change)
- Account Balance (e.g., "Balance: $5,000")
- Stock Prices (e.g., "AAPL: $150.25" with "+2.3%")
- Weather Data (e.g., "San Francisco" with "72°F")
Request Format
{
"schema_type": "summary",
"content": {
"title": "Daily Revenue",
"primary_value": "$12,345",
"secondary_value": "+15%" // optional
},
"metadata": {
"source": "stripe",
"external_id": "rev-2026-02-08"
},
"intent": {
"update_widget": true,
"send_push": true
}
}Example: Stripe Revenue
curl -X POST "https://glance-api.fly.dev/ingest/YOUR_FEED_ID" \
-H "Authorization: Bearer YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema_type": "summary",
"content": {
"title": "Today's Revenue",
"primary_value": "$1,247.50",
"secondary_value": "+18%"
},
"metadata": {
"source": "stripe-webhook"
},
"intent": {
"update_widget": true,
"send_push": false
}
}'Status Schema
Display system status with visual indicators (success, warning, error). Ideal for monitoring uptime, deployments, or health checks.
Use Cases
- API Health Monitoring (e.g., "All Systems Operational")
- Deployment Status (e.g., "Deploy Succeeded")
- Server Uptime (e.g., "Online - 99.9% uptime")
- Build Status (e.g., "CI/CD: Passing")
Request Format
{
"schema_type": "status",
"content": {
"title": "API Status",
"status": "success", // "success", "warning", "info", or "error"
"message": "All systems operational",
"details": "Last checked: 2 min ago" // optional
},
"intent": {
"update_widget": true,
"send_push": true // only send push on errors
}
}Example: Server Health Check
curl -X POST "https://glance-api.fly.dev/ingest/YOUR_FEED_ID" \
-H "Authorization: Bearer YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema_type": "status",
"content": {
"title": "Production API",
"status": "success",
"message": "Fully Connected",
"details": "Response time: 45ms"
},
"intent": {
"update_widget": true,
"send_push": false
}
}'Counter Schema
Display numerical counts with optional trends and units. Perfect for tracking signups, users, events, or any incrementing metrics.
Use Cases
- Active Users (e.g., "2,314 users" with "+12% trend")
- Total Signups (e.g., "1,543 signups this week")
- Inventory Count (e.g., "48 items in stock")
- Queue Length (e.g., "12 jobs pending")
Request Format
{
"schema_type": "counter",
"content": {
"title": "Active Users",
"count": 2314,
"unit": "users", // optional
"trend": "up", // "up", "down", or "flat" - optional
"trendValue": "+12%", // optional
"trendSemantic": "positive", // "positive", "negative", "neutral" - optional
"subtitle": "This week" // optional
},
"intent": {
"update_widget": true,
"send_push": false
}
}Example: User Signups
curl -X POST "https://glance-api.fly.dev/ingest/YOUR_FEED_ID" \
-H "Authorization: Bearer YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema_type": "counter",
"content": {
"title": "New Signups",
"count": 127,
"unit": "users",
"trend": "up",
"trendValue": "+23%",
"trendSemantic": "positive",
"subtitle": "Last 24 hours"
},
"intent": {
"update_widget": true,
"send_push": false
}
}'Approval Schema
Request user approval via push notification with interactive actions. The user can Approve, Reject, or Reply with a free-text note. Their response is sent back to your webhook callback URL.
Use Cases
- Deployment Approvals (e.g., "Deploy v2.3.0 to production?")
- Expense Approvals (e.g., "Approve $5,000 expense?")
- Access Requests (e.g., "Grant admin access to John?")
- Critical Alerts (e.g., "Server CPU at 95% - restart?")
Request Format
{
"schema_type": "approval",
"content": {
"description": "Deploy v2.3.0 to production?"
},
"metadata": {
"deployment_id": "deploy-123"
},
"intent": {
"send_push": true // approval always sends push
},
"callback": {
"url": "https://your-api.com/webhook/approval",
"method": "POST"
}
}Callback Response
When the user taps an action (Approve / Reject / Reply), Glance POSTs to your callback URL. The metadata.note field is only present when the user chose Reply and typed a message.
{
"approval_id": "abc123...",
"feed_id": "xyz789...",
"action": "Reply", // "Approve", "Reject", or "Reply"
"responded_at": "2026-02-08T12:34:56Z",
"user_id": "usr_...",
"metadata": {
"decision": "reply", // "approve", "reject", or "reply"
"note": "Needs QA sign-off first", // present only on Reply
"feed_event_id": 456
}
}Example: Deployment Approval
curl -X POST "https://glance-api.fly.dev/ingest/YOUR_FEED_ID" \
-H "Authorization: Bearer YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema_type": "approval",
"content": {
"description": "Deploy v2.3.0 to production?"
},
"metadata": {
"deployment_id": "v2.3.0",
"environment": "production"
},
"intent": {
"send_push": true
},
"callback": {
"url": "https://api.yourapp.com/deployments/callback",
"method": "POST"
}
}'Custom Schema
Display fully custom image-based widgets on your home screen. You supply the images — Glance renders them at each widget size. Supports separate light and dark mode variants, and an optional tap-through URL. Free plans include 1 custom feed; Pro plans include 2; Power plans include unlimited.
Use Cases
- Branded dashboards (e.g., export a chart image from your BI tool and push it to your widget)
- Figma or design previews (e.g., share design snapshots directly on your home screen)
- Generated infographics (e.g., a Python script renders a graph and uploads it each morning)
- Live scoreboard or status boards with a fully custom layout
Widget Sizes
At least one size is required per request. Accepted formats: PNG, JPEG, WebP. Maximum 2 MB per image. Images are validated against the target aspect ratio (±5% tolerance) and a minimum resolution — they do not need to be exactly the listed pixel dimensions, but must be at least that large and match the aspect ratio within 5%. After passing validation, images are automatically resized to the exact target dimensions before being stored.
| Size key | Aspect ratio | Min. resolution | Widget size |
|---|---|---|---|
| small | 1:1 (= 1.000) | 474 × 474 px | Small square |
| medium | ~2.14:1 (= 1014 ÷ 474) | 1014 × 474 px | Medium wide |
| large | ~0.955:1 (= 1014 ÷ 1062) | 1014 × 1062 px | Large tall |
Method 1 — Hosted Image URLs
If you already host your images (e.g. on a CDN, S3, or any public HTTPS URL), send a standard JSON POST to the ingest endpoint. The image_url_dark field is optional — if omitted, the light image is used in dark mode too.
{
"schema_type": "custom",
"content": {
"small": {
"image_url": "https://cdn.example.com/widget-small.png",
"image_url_dark": "https://cdn.example.com/widget-small-dark.png" // optional
},
"medium": {
"image_url": "https://cdn.example.com/widget-medium.png",
"image_url_dark": "https://cdn.example.com/widget-medium-dark.png" // optional
},
"large": {
"image_url": "https://cdn.example.com/widget-large.png"
},
"widget_url": "https://dashboard.example.com" // optional — opens on tap
},
"intent": {
"update_widget": true,
"send_push": false
}
}Example: CI Pipeline Pushing a Chart (Hosted URL)
curl -X POST "https://glance-api.fly.dev/ingest/YOUR_FEED_ID" \
-H "Authorization: Bearer YOUR_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema_type": "custom",
"content": {
"small": {
"image_url": "https://cdn.acme.com/charts/revenue-small.png",
"image_url_dark": "https://cdn.acme.com/charts/revenue-small-dark.png"
},
"medium": {
"image_url": "https://cdn.acme.com/charts/revenue-medium.png",
"image_url_dark": "https://cdn.acme.com/charts/revenue-medium-dark.png"
},
"widget_url": "https://acme.metabase.com/dashboard/revenue"
},
"metadata": {
"source": "ci-pipeline",
"external_id": "build-4821"
},
"intent": {
"update_widget": true,
"send_push": false
}
}'Method 2 — Upload Images Directly
If you don't host your own images, upload them directly using a multipart form POST to the upload endpoint. Glance stores them and generates the URLs automatically. Uploaded images are validated against the required aspect ratio (±5% tolerance) and minimum resolution — the request will be rejected if either check fails. Images are then resized to the exact target dimensions before storage.
curl -X POST "https://glance-api.fly.dev/ingest/YOUR_FEED_ID/upload" \
-H "Authorization: Bearer YOUR_WRITE_KEY" \
-F "small_image=@widget-small.png" \
-F "small_image_dark=@widget-small-dark.png" \
-F "medium_image=@widget-medium.png" \
-F "large_image=@widget-large.png" \
-F "widget_url=https://dashboard.example.com" \
-F 'intent={"update_widget":true,"send_push":false}'| Form field | Required | Description |
|---|---|---|
| small_image | At least one size | Light mode small widget (1:1 aspect ratio, min 474 × 474 px) |
| medium_image | At least one size | Light mode medium widget (~2.14:1 aspect ratio, min 1014 × 474 px) |
| large_image | At least one size | Light mode large widget (~0.96:1 aspect ratio, min 1014 × 1062 px) |
| small_image_dark | Optional | Dark mode variant for small widget |
| medium_image_dark | Optional | Dark mode variant for medium widget |
| large_image_dark | Optional | Dark mode variant for large widget |
| widget_url | Optional | URL to open when the widget is tapped |
| intent | Optional | JSON string, e.g. {"update_widget":true} |
| metadata | Optional | JSON string, e.g. {"source":"figma"} |
Example: Python Script Uploading a Generated Graph
import requests
feed_id = "YOUR_FEED_ID"
write_key = "YOUR_WRITE_KEY"
with open("graph-small.png", "rb") as sm, \
open("graph-medium.png", "rb") as md:
response = requests.post(
f"https://glance-api.fly.dev/ingest/{feed_id}/upload",
headers={"Authorization": f"Bearer {write_key}"},
files={
"small_image": ("graph-small.png", sm, "image/png"),
"medium_image": ("graph-medium.png", md, "image/png"),
},
data={
"widget_url": "https://grafana.acme.com/d/xyz",
"intent": '{"update_widget":true,"send_push":false}',
"metadata": '{"source":"morning-cron"}',
},
)
print(response.json())Widget Tap URL
Including a widget_url in your payload makes the widget tappable. When the user taps it, the URL opens in their default browser. Use this to link to a dashboard, report, or any relevant page. If omitted, tapping the widget does nothing.
Tip: The widget_url is stored per-update — each time you push a new image you can also change the destination URL.
Zapier Integration
Use Zapier's Webhooks by Zapier action to send data to Glance from thousands of apps.
Setup Steps
- Create a Zap: Choose your trigger app (e.g., Stripe, Gmail, etc.)
- Add Action: Search for "Webhooks by Zapier" and select "POST"
- Configure URL: Enter your Glance webhook URL
- Set Headers:
Authorization: Bearer YOUR_WRITE_KEYContent-Type: application/json
- Payload Type: Select "json"
- Data: Map your trigger fields to the Glance schema format
Example: Stripe Payment → Summary
In the Webhooks by Zapier "Data" field, use:
{
"schema_type": "summary",
"content": {
"title": "Latest Payment",
"primary_value": "{{amount}}",
"secondary_value": "{{customer_email}}"
},
"intent": {
"update_widget": true,
"send_push": true
}
}Make (Integromat) Integration
Use Make's HTTP module to send data to Glance from your automation scenarios.
Setup Steps
- Add HTTP Module: Search for "HTTP" and select "Make a request"
- URL: Enter your Glance webhook URL
- Method: POST
- Headers:
- Name:
Authorization, Value:Bearer YOUR_WRITE_KEY - Name:
Content-Type, Value:application/json
- Name:
- Body type: Raw
- Content type: JSON (application/json)
- Request content: Map your data to the Glance schema
Tip: Use Make's JSON module to build your payload structure before passing it to the HTTP module.
n8n Integration
Use n8n's HTTP Request node to send data to Glance from your self-hosted workflows.
Setup Steps
- Add HTTP Request Node: Drag the HTTP Request node into your workflow
- Authentication: Select "Header Auth"
- Name:
Authorization - Value:
Bearer YOUR_WRITE_KEY
- Name:
- Request Method: POST
- URL: Your Glance webhook URL
- Body Content Type: JSON
- Specify Body: Using Fields Below
- Body: Add fields matching your schema
Example Node Configuration
{
"schema_type": "counter",
"content": {
"title": "{{ $json.metric_name }}",
"count": {{ $json.count }},
"trend": "{{ $json.trend }}"
},
"intent": {
"update_widget": true,
"send_push": false
}
}Rate Limits & Quotas
Rate limits are enforced per feed based on your subscription tier.
| Plan | Events/Minute | Events/Day | History |
|---|---|---|---|
| Free | 1 | 24 | 7 days |
| Pro | 3 | 96 | 14 days |
| Power | 5 | 288 | 45 days |
Throttling: If you exceed your rate limit, requests will be rejected with a 429 status code. Events marked as "throttled" appear in your event log but don't update widgets or send push notifications.