Push

Devices

Your backend registers each device token with the API, tied to your own user ID, and retires it on logout.

Register a device

Your backend registers the token your app received with PUT /v1/push/devices. The call is an upsert on the app, token and mode, so calling it on every app launch is fine.

The body has app_id, token (up to 512 characters of letters, digits, _, :, . and -), platform (ios or android; a browser registers with web and subscription in place of the token, as the Web push page shows), user_id (your own identifier for the person, up to 255 characters) and, for iOS, apns_environment: sandbox for development builds and production for the rest. A token only works in the environment its build was signed for. Add encryption_public_key, the public key the HonkIO push package made on the device, so honkio encrypts its pushes: a new key replaces the stored one. Registering the same token again without the field keeps its key, but a new token (after an APNs or FCM token refresh) is a new device with no key unless the key comes with it, so send the key with every token you register: the HonkIO packages give your app the key together with the token. Only an explicit null removes it; that device's pushes then go in plain text or, on an app that requires encryption, it gets none (ENCRYPTION_KEY_MISSING) until it registers a key again. A device carries encryption_key_id, never the key. A browser takes no encryption_public_key: web push is already encrypted to it.

Registering a device or a browser needs the push_devices permission's w and removing its d; listing devices needs push r, and sending push w. A key for the backend that only registers and removes devices can hold push_devices alone. Over OAuth, the push:devices scope grants it; push:send does not.

// Call this from your backend when the app reports its token.
const { data: device, error } = await honkio.push.devices.register({
  appId: 'APP_ID',
  token: 'DEVICE_TOKEN',
  platform: 'ios', // or 'android'
  userId: 'user_1042', // your own identifier for this person
  apnsEnvironment: 'production', // iOS only: 'sandbox' for development builds
  encryptionPublicKey: 'DEVICE_PUBLIC_KEY', // the key the HonkIO push package made on the device
})
if (error) throw new Error(error.message)
console.log(device.id, device.active, device.encryption_key_id)

Registering a token that already exists under another user_id moves it to the new user. After a logout and a login on a shared phone, pushes for the old user no longer reach it.

Each user keeps at most 20 active devices. A new one beyond that retires the least recently seen device and fires push_device.deactivated with the reason DEVICE_LIMIT. Each app keeps at most 1,000,000 active devices in live mode and 1,000 in test mode: a new device beyond that is refused with 409 PUSH_DEVICE_LIMIT.

When a device is retired

Apple and Google tell honkio when a token is no longer valid, for example after an uninstall. honkio deactivates the device and fires push_device.deactivated with the reason UNREGISTERED or INVALID_TOKEN. A token issued for another app (Apple's DeviceTokenNotForTopic, a token for another bundle ID, or Google's SENDER_ID_MISMATCH, a token from another Firebase project) is judged by whether the credential has worked before: once a live push has been accepted with it, the device is the odd one out, so it is deactivated with the reason APP_MISMATCH and the credential is left alone. Before then, the app's setup is the likely cause (a wrong bundle ID or Firebase project), so the credential is marked invalid, push_app.credentials_invalid fires and the device is kept. Either way the delivery fails with APP_MISMATCH. A key Apple does not allow for your bundle ID (TopicDisallowed) is always a credential problem.

Call DELETE /v1/push/devices/:id on logout. Registering the token again reactivates it. Deactivated devices are deleted after 30 days.

GET /v1/push/devices lists devices, with app_id, user_id and active filters. A test key sees only test devices and a live key only live ones.