Live notification payload reference
Each payload constructor selects a template. start and update take the same shape—pass the complete state every time, because each update replaces the previous one rather than patching it.
start returns the notification’s ID. Keep it: update and end both take it, and it’s what you hand your server if you want it to take over.
The field names match the ones your server sends through the API. The plugin flattens them into a single payload: header is a static attribute, and everything else is content state.
Multi-step tracker
final activityId = await CustomerIO.liveActivities.start(
LiveActivityPayload.segments(
header: "Chica's Tacos",
status: 'Preparing your order',
substatus: "We'll let you know when it's on the way",
segmentsTotal: 4,
segmentsComplete: 2,
trailingText: '25 min',
),
);
| Field | Type | Required | Description |
|---|---|---|---|
header | String | Yes | Static header line. Set at start; can’t change. |
status | String | Yes | Primary status line. |
substatus | String? | No | Secondary status line. |
segmentsTotal | int | Yes | Total number of steps. Capped at 20 steps. |
segmentsComplete | int | Yes | Steps finished so far. Clamped to 0–segmentsTotal. |
trailingText | String? | No | Trailing text, such as an ETA. Typically matters for iOS. Android has a single slot for the message body; when both substatus and trailingText are set, the message body renders substatus and drops trailingText. |
Countdown timer
final activityId = await CustomerIO.liveActivities.start(
LiveActivityPayload.countdownTimer(
header: 'Summer Sale',
title: 'Flash sale ends in',
statusMessage: '30% off everything',
endTime: 1753603600,
),
);
| Field | Type | Required | Description |
|---|---|---|---|
header | String | Yes | Static header line. Set at start; can’t change. |
title | String | Yes | Primary title line. |
statusMessage | String? | No | Status message below the title. |
endTime | int? | No | Target time in epoch seconds, not milliseconds. Omit it to render the finished state. |
Custom
A custom notification has no schema—you render it, so the SDK passes your values through untouched.
final activityId = await CustomerIO.liveActivities.start(
LiveActivityPayload.custom(
data: {
'driver': 'Sam',
'vehicle': 'Blue Prius',
'minutesAway': '4',
},
),
);
Every value in data must be a string, and it carries the complete state on every update. Nested objects and arrays aren’t supported, and the platforms disagree on them—iOS drops them and Android turns them into strings. Flatten anything structured before you send it.