Devices
Push token registry API — register, list, and revoke devices used for mobile push notifications.
Manage the per-user push token registry. Each row in user_devices is one channel-tagged endpoint that the notification dispatcher targets when fanning out a notification to that channel.
The current set of channels is mobile_push. Each row also carries a platform (ios | android) so the adapter can route per-device — iOS rows go to APNs today, Android rows are reserved for the FCM transport that will land later. Future channels (Telegram chat IDs, webhook URLs, etc.) will reuse this same table.
All endpoints are user-only. Agent API keys receive 403. Auth is via the standard JWT cookie.
POST /v1/devices
Register or refresh a device. The token is the unique key — re-registering the same token under a different user atomically reassigns ownership (Apple may reissue tokens after a device wipe + re-login). Re-registering the same token under the same user updates last_seen_at and any changed metadata.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
channel | string | Yes | Push channel. Currently only mobile_push is accepted; unknown values return 400. |
platform | string | Yes | ios or android. Determines which transport the dispatcher uses for this row. |
token | string | Yes | Channel-specific device token. For platform: "ios" this is the hex APNs device token. |
environment | string | No | sandbox or production. Anything other than sandbox is treated as production. iOS-only — picked from the embedded provisioning profile by the Swift client. |
app_version | string | No | App version for diagnostics (e.g., 2.1.0). |
device_model | string | No | Device model (e.g., iPhone15,3). |
os_version | string | No | OS version (e.g., iOS 18.2). |
Response
// 201
{
"device": {
"id": "uuid",
"channel": "mobile_push",
"platform": "ios",
"environment": "production",
"app_version": "2.1.0",
"device_model": "iPhone15,3",
"os_version": "iOS 18.2",
"last_seen_at": "2024-01-15T10:00:00.000Z",
"created_at": "2024-01-15T10:00:00.000Z"
}
}GET /v1/devices
List the authenticated user's registered devices, ordered by last_seen_at descending.
Response
{
"devices": [
{
"id": "uuid",
"channel": "mobile_push",
"platform": "ios",
"environment": "production",
"app_version": "2.1.0",
"device_model": "iPhone15,3",
"os_version": "iOS 18.2",
"last_seen_at": "2024-01-15T10:00:00.000Z",
"created_at": "2024-01-15T10:00:00.000Z"
}
]
}The raw token is intentionally not returned — only the server needs it.
DELETE /v1/devices/:id
Hard-delete a device row. Use this when the user signs out of the iOS app, switches accounts, or wants to stop receiving push on that device.
The server also hard-deletes a device row automatically when APNs returns 410 Unregistered or 400 BadDeviceToken for that token — the next push attempt to a stale token cleans itself up. See Notifications concepts.
Response
{ "id": "uuid" }Returns 404 if the device does not exist or belongs to another user.
