Skip to content

Payload Reference

Use this as the single source of truth for the /notify request body.

Authentication (required)

Send your secret as a Bearer token on every request:

POST /notify
Authorization: Bearer <uniqueID>
Content-Type: application/json

Complete JSON example

{
"job_id": "deploy-prod",
"title": "Production Deploy",
"message": "Running migrations...",
"status": "running",
"action": "update",
"layout": "progress",
"theme": "default",
"metric": "Step 2/5",
"progress": 0.4,
"secondaryMetric": "LIVE",
"metricA": "3",
"metricB": "1",
"subA": "HOME",
"subB": "AWAY",
"icon": "bolt.fill",
"accentColor": "#00CFFF"
}

Field reference

FieldTypeRequiredAllowed / formatDefaultAvailabilitySince (app)Notes
job_idstringYes1-64 chars, A-Z a-z 0-9 _ -noneAll tiers1.0Routing key only; not displayed as title.
titlestringNonon-empty text recommendedderived from message or "Island Pulse"All tiers1.0Display title in Live Activity UI.
messagestringYes*non-empty stringnoneAll tiers1.0Primary body text. Required for start/update; not required for end.
statusstringNorunning | success | failedrunningAll tiers1.0Visual status state.
actionstringNostart | update | endauto-selectedAll tiers1.0Omit for normal auto-routing behavior.
layoutstringNodefault | progress | score | sportsdefaultPro for non-default1.0Free requests are normalized to default.
themestringNoimplementation-defineddefaultApp feature dependent1.0Optional visual theme hint.
metricstringNoshort textnoneAll tiers1.0KPI/auxiliary metric.
progressnumberNo0.0-1.0 (or 0-100)noneAll tiers1.0Values above 1 are normalized as percentages.
secondaryMetricstringNoshort textnoneAll tiers1.0Secondary badge/label text.
metricAstringNoshort textnoneAll tiers1.0Sports/dual metric left value.
metricBstringNoshort textnoneAll tiers1.0Sports/dual metric right value.
subAstringNoshort textnoneAll tiers1.0Sports/dual metric left sublabel.
subBstringNoshort textnoneAll tiers1.0Sports/dual metric right sublabel.
iconstringNoSF Symbol namelayout defaultAll tiers1.0Per-push icon override.
accentColorstringNoCSS color or hexapp/theme defaultAll tiers1.0Per-push accent override.

Since (app) is the first iOS app version that understands the field. The service accepts a field as soon as it is deployed, but an installed app only shows what it knows how to render, and unknown fields are ignored. Where each field appears (Lock Screen, compact island, expanded island) is listed in Layouts and changes between app versions; see the Changelog.

Tier behavior notes

  • Free tier allows one active job_id at a time per token.
  • Free tier uses default layout only; non-default layout values are coerced to default.
  • Sending a different active job_id on free returns 403 FREE_TIER_JOB_LOCKED (TIER_LIMIT_EXCEEDED support code).
  • Sending start for a job_id that is already running returns 409 ACTIVITY_ALREADY_RUNNING (all tiers). Send updates instead, or end the activity first.
  • Pro tier supports multiple concurrent job streams (up to iOS system limits).

Versions and compatibility

  • Payload fields are additive. A new field never changes the meaning of an existing one, and apps that don’t know a field ignore it.
  • Every update replaces the whole state, so send layout and all of its fields on every update, not only the first.
  • Send metric alongside a layout’s own fields (for example the batting score next to metricA on a sports update). Apps older than 1.3 show only metric in the compact island, so it works as a fallback.

Common errors

HTTPErrorMeaning
400MISSING_UNIQUE_IDMissing or invalid Bearer token.
400MISSING_JOB_IDjob_id missing or empty.
400INVALID_JOB_IDjob_id format invalid.
400INVALID_ACTIONaction is not start/update/end.
403FREE_TIER_JOB_LOCKEDFree tier: a different job_id is already active. End it first.
409ACTIVITY_ALREADY_RUNNINGA Live Activity for this job_id is already running. Send updates or end it before starting again.
502APNS_PUSH_FAILEDAPNs rejected delivery.
502APNS_RECOVERY_FAILEDUpdate token was dead and start recovery failed too.