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://api.glance.app/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://api.glance.app/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://api.glance.app/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://api.glance.app/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's 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/Defer), Glance will POST to your callback URL:
{
"feed_id": "abc123...",
"action_type": "approve", // "approve", "reject", or "defer"
"event_id": "456",
"timestamp": "2026-02-08T12:34:56Z",
"metadata": {
"deployment_id": "deploy-123"
}
}Example: Deployment Approval
curl -X POST "https://api.glance.app/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
Pro & Power onlyDisplay fully custom image-based widgets on your home screen. You supply the images — Glance renders them pixel-perfect at each widget size. Supports separate light and dark mode variants, and an optional tap-through URL. One custom feed is allowed per account.
Paid Feature: Custom widgets are available on Pro and Power plans only. Attempting to create a custom feed on the Free plan will be rejected.
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
Images must be provided at @3x retina resolution. At least one size is required per request. Accepted formats: PNG, JPEG, WebP. Maximum 2 MB per image.
| Size key | Dimensions (px) | Widget size |
|---|---|---|
| small | 474 × 474 | Small square |
| medium | 1014 × 474 | Medium wide |
| large | 1014 × 1062 | 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://api.glance.app/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 exact pixel dimensions — the request will be rejected if the dimensions don't match.
curl -X POST "https://api.glance.app/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 (474 × 474 px) |
| medium_image | At least one size | Light mode medium widget (1014 × 474 px) |
| large_image | At least one size | Light mode large widget (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://api.glance.app/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 | 6 | 100 | 7 days |
| Pro | 60 | 1,000 | 14 days |
| Power | 90 | 2,400 | 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.