This request ends an activity started via /start.
It sends the final push message to the target devices, containing content representing the final state (e.g., "Delivered ✓", "Match ended").
It deletes the entire activity record on Insider's side.
The activity transitions to DEAD. All subsequent calls with the same activity_id return a 404 NOT_FOUND response.
/end does not physically remove the activity from the device. Insider One only delivers the final content and clears its own state. The activity on the device disappears according to Apple's stale-after/dismissal-date rules, or when the user manually swipes it away.
Endpoint and headers
POST /api/v1/live-activity/end
Headers
Header | Value |
|---|---|
X-Api-Key |
Body parameters
Below are the parameters for the request body.
Parameter | Description | Data Type | Required |
|---|---|---|---|
activity_id | The ID returned by /register | String | Yes |
activity_type | Same as in register; iOS ActivityAttributes class name | String | Yes |
content | Live activity content | Object | Yes |
title | Live activity title | String | Yes |
message | Live activity body/secondary message | String | Yes |
content_state | Key/value map that exactly matches the ContentState struct in the iOS application | Object | Yes |
When target_devices is present, pushes are sent only to devices matching the (insider_id, udid) pairs in the list.
activity_id cannot be empty.
activity_type cannot be empty.
Sample body
Below is a sample request body.
{
"activity_id": "550e8400-e29b-41d4-a716-446655440000",
"activity_type": "OrderTrackingAttributes",
"content": {
"title": "Delivered ✓",
"message": "Your order has been delivered successfully.",
"content_state": {
"status": "delivered",
"deliveredAt": "2026-05-20T14:32:00Z"
}
}
}Body examples
Since /end is the final push, content represents the final state; the attributes block may be resent as well.
Delivery delivered
{
"activity_id": "<activity_id>",
"activity_type": "DeliveryActivityAttributes",
"content": {
"title": "Order delivered",
"message": "Enjoy!",
"content_state": {
"status": "delivered",
"etaMinutes": 0
},
"attributes": {
"courierName": "Yusuf K."
}
}
}.png)
Workout finished
{
"activity_id": "<activity_id>",
"activity_type": "WorkoutActivityAttributes",
"content": {
"title": "Workout completed",
"message": "30 min · 250 kcal",
"content_state": {
"phase": "finished",
"elapsedSeconds": 1800,
"calories": 250
},
"attributes": {
"workoutType": "Running"
}
}
}
Match ended
{
"activity_id": "<activity_id>",
"activity_type": "MatchActivityAttributes",
"content": {
"title": "Match ended",
"message": "Home FC 2 - 1 Away FC",
"content_state": {
"homeScore": 2,
"awayScore": 1,
"period": "full_time",
"minute": 90
},
"attributes": {
"homeTeam": "Home FC",
"awayTeam": "Away FC"
}
}
}
The /end call sends the final push; the device shows this message until the stale-after period expires or the user dismisses it.
Critical rules
Irreversible: dead state
After /end is called successfully:
The activity record on Insider One's end is immediately deleted.
Every subsequent call (/start, /update, /end) with the same activity_id returns 404 NOT_FOUND.
You cannot resurrect the activity. To start fresh, create a new activity with /register.
// Response of a second /end call
{
"error": "activity not found",
"code": "NOT_FOUND"
}Not physically removed from the device
The /end call only delivers the final content to the device. On the device, the live activity:
Is automatically dimmed when the stale-after period expires (Apple default ~4 hours).
Disappears from the Dynamic Island / Lock Screen when the dismissal date is reached.
Vanishes immediately if the user dismisses it with a manual swipe.
The content you send with /end should represent the final state ("Completed", "Finished", "Cancelled"). This is the last view the user sees until they dismiss the activity.
SDK sync gate still applies
Like /update, /end sends pushes only to synced devices:
Situation | Behavior |
|---|---|
All target devices are synced. | Final push goes to all of them: 200 OK |
Some are synced, some are not. | Pushes go to the synced ones. 200 OK + skipped_not_synced: N. The activity is still deleted. |
All target devices are unsynced. | 412 PUSH_TOKEN_NOT_SYNCED: No push is sent, the activity is not deleted. |
If you receive 412 PUSH_TOKEN_NOT_SYNCED, the activity is still alive. Wait a short while and retry, or accept that the devices are offline and let the ends_at TTL force-close it.
Content responsibility
Like /start and /update, /end is a proxy:
content passes directly into the Apple push.
content_state enums must match the iOS values exactly.
Sample responses
Success response 200
{
"status": "success",
"sessions_triggered": 845,
"skipped_not_synced": 5
}Below are the fields that return in the response.
Field | Type | Description |
|---|---|---|
status | String | Always "success" |
sessions_triggered | Int | The number of final push messages delivered to Apple |
skipped_not_synced | Int (omitempty) | The number of devices that did not receive the final message because their token had not synced |
After the response arrives, the activity is deleted on Insider One's end. A second /end call returns 404; this is expected behavior.
Error responses
Refer to Error Codes for details.
Limitations
The rate limit is 1,000 requests per minute.
Always call /end. When the activity's validity period (ends_at) expires, the record on Insider One's side is automatically deleted, but this does not send a final push to the devices. To close the user experience cleanly, always call /end explicitly.
Targeted end: If you send the final push to specific devices via target_devices, the activity is still fully deleted (Insider clears its state). Targeted end is not a "partial end"; it closes the activity as a whole and only sends the push to the selected devices.
Multiple /end calls: If the first one succeeded, the second returns 404. Treat it as an "already closed" signal, not an error.
The content of the /end call matters. The device shows this message until it is dismissed or stale-after expires; sending a half-baked or wrong final state is a poor user experience.