Devices
Push token registry API — register, list, and revoke devices used for iOS 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 ios_push. Adding Android FCM, Telegram chat IDs, or webhook URLs in the future 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 ios_push is accepted; unknown values return 400. |
token | string | Yes | Channel-specific device token. For ios_push this is the hex APNs device token. |
environment | string | No | sandbox or production. Anything other than sandbox is treated as production. |
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": "ios_push",
"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": "ios_push",
"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.
