The state object
Every field that controls what the card shows on the phone.
state is what the card shows. Which layout shows which field is in layouts. The rules:
- On an update (and an end's
finalState), the fields sent merge into the saved state. Fields not sent keep their value. versusmerges the same way, one level down.segmentsis replaced whole.- To clear a field, send it as
""(or[]forsegments). - The whole state must be 16KB or less.
Android draws a system notification from the text, accent color, icon, Picture photo, progress bar, scores, league logo, and action button. Fields marked iPhone only do nothing on Android.
Layout and text
| Field | Type | Default | Instructions |
|---|---|---|---|
layout | string | progress | progress, picture, versus, or countdown. Set it on start. Change it on an update to switch the type. |
primaryText | string | "" | The headline on Progress, the caption on Picture. Also the title of every alert, so set it on every layout. |
secondaryText | string | "" | The line under the headline, and the body of every alert. On Countdown, the name next to the clock. |
stage | string | none | A short word for the current step ("On the way"). iPhone shows it in the compact Dynamic Island, on Progress only. Android 16 shows it in the status chip. Keep it near 7 characters. |
isComplete | boolean | false | true for the final state. Progress shows "Done" in the compact Dynamic Island. The card stays until it is ended. |
Colors
Colors are #RRGGBB text. There is no text color field: text turns black or white to stay readable. The Dynamic Island is always dark.
| Field | Type | Default | Instructions |
|---|---|---|---|
accentColorHex | string | blue | The brand color: the progress bar, tints, and the Android accent. On a custom background color, the bar is black or white instead. brand.color sets it when the state does not. |
backgroundColorHex | string | black | The Lock Screen background (Progress, Versus, Countdown). iPhone only. |
backgroundGradientHex | string | none | A second color. With backgroundColorHex, the background becomes a gradient (Progress, Versus, Countdown). iPhone only. |
Images
Image fields take a full https URL the phone can download. Use WebP. Shapes and sizes are in images that fit. A new image URL on an update restarts the card, so keep URLs the same between calls.
| Field | Type | Default | Instructions |
|---|---|---|---|
headerIconUrl | string | none | The logo on Progress and Countdown, and the small mark on Picture. Drawn as a rounded square. |
backgroundImageUrl | string | none | A full-size image behind the card: the Picture photo, or a Progress or Versus background. A dark layer keeps text readable. Countdown does not show it. |
lockScreenImageUrl | string | none | A Lock Screen version of headerIconUrl, when the Lock Screen needs a different image than the dark Dynamic Island. Used by Progress and Picture. |
islandImageUrl | string | none | Picture only. A separate photo for the Dynamic Island, which is smaller than the Lock Screen. Falls back to the Lock Screen photo. iPhone only. |
androidIconUrl | string | none | Replaces headerIconUrl on Android. |
androidImageUrl | string | none | Replaces backgroundImageUrl on Android. Picture shows it as the expanded photo. |
immersive | boolean | false | true removes the dark layer over backgroundImageUrl. Use it only with dark art. iPhone only. |
Progress
| Field | Type | Default | Instructions |
|---|---|---|---|
progress | number | 0 | Bar fill from 0 to 1. With segments in the segmented style, the share of complete steps is used instead. |
progressStyle | string | segmented | segmented (one capsule per step) or linear (one bar, its ends labeled with the first and last step labels). |
segments | object[] | none | The steps, each { "label": string, "complete": boolean }. Up to 12. Send the full list on every update. |
estimatedMinutes | number | none | Whole minutes. Shows "N min" in the compact Dynamic Island when no stage is set. 0 hides it. iPhone only. |
Countdown
| Field | Type | Default | Instructions |
|---|---|---|---|
countdownTo | number | none | The target time in Unix epoch seconds, as a number (not milliseconds or text). The clock runs on the phone. An alert is sent when the time is reached. |
countdownStyle | string | auto | hms (00:00:00), days, hours, months, years, or auto. auto shows a running clock (00:00:00) in the last 36 hours, and the largest whole unit before that. |
completionText | string | none | Shown in place of the clock once the time is reached, and the title of that alert. Without it, iPhone shows secondaryText and Android shows primaryText. |
Action button
To remove the button, send all three fields as "".
| Field | Type | Default | Instructions |
|---|---|---|---|
actionLabel | string | none | The button text ("Watch Live"). iPhone shows it on Picture and Versus, on the Lock Screen and the expanded Dynamic Island, not the compact one. Android shows it on any layout when actionURL is set. |
actionURL | string | none | The http or https URL the button opens. Other URLs are dropped. |
actionColorHex | string | red (Versus), orange (Picture) | The button color. iPhone only. |
The versus object
Set this inside state when layout is versus.
| Field | Type | Default | Instructions |
|---|---|---|---|
leftName / rightName | string | "" | The two sides' names. |
leftScore / rightScore | string | "0" | Scores as text, so "12", "$1,500", and "X" all work. Numbers are turned into text. |
leftStatus / rightStatus | string | "" | A small line under each name ("Winner"). |
activeSide | string | none | "left" or "right". When the Dynamic Island is at its smallest, it shows that side's logo. |
leftColorHex / rightColorHex | string | text color | Each side's score color. iPhone only. |
centerLabel | string | none | Small text in the middle ("Map"). |
centerValue | string | none | The value under it ("Overpass"). |
leftImageUrl / rightImageUrl | string | none | The two logos. Transparent PNGs look best. |
centerImageUrl | string | none | An image in the middle (an auction item, a map). |
sourceLogoUrl | string | none | The league or brand logo: the bottom strip on iPhone, the Apple Watch tile, and the Android icon. |
The brand object
Optional, set at the top level of the start call. Change it later with POST /api/branding. The site shown under the brand name comes from the page that hosts the launch button, so it is not a brand field.
| Field | Type | Instructions |
|---|---|---|
title | string | The activity's name in the app's list. Falls back to name. |
name | string | The brand name ("Acme"). Shown in the app, on the Versus bottom strip, and as the alert title when primaryText is empty. Leave it out to show no source name. |
logo | string | The logo URL for the app's cover. Falls back to headerIconUrl, then the WebActivity logo. |
description | string | A short line under the title on the cover. Falls back to secondaryText. |
color | string | The brand color as #RRGGBB. Sets accentColorHex when the state has none. |









