Devices
Registration, user identifiers, permissions, tags, and token invalidation.
A device is an APNs or FCM token registered to one Carillon app.
Use its id to target it in audience.device_ids.
Registration
The SDK calls POST /v1/devices with a mobile key. Registering the same token in the same app
updates the existing device and returns the same ID. A new token creates a new device.
If you already have a provider token, you can register it with the API or import tokens from CSV.
User identifiers
Set external_id with identify() and clear it on sign-out with clearIdentity()
(or identify(null) in React Native).
- Two devices can have the same
external_id. - Changing the signed-in user updates the identifier on the existing device.
- A reinstall that obtains a new token creates a new device. The old token remains until the provider invalidates it.
external_id is optional. It does not replace the device ID used in a send request.
What registration collects
| Field | Where it comes from |
|---|---|
token | The APNs or FCM token, exactly as the device received it |
platform | ios or android |
environment | Detected by the SDK from the build it is running in, never configured |
external_id | identify(), and null erases it |
tags | setTags(), replaced whole rather than merged |
timezone_id | The IANA identifier the OS reports, never an offset |
locale | BCP 47 |
app_version, app_build | The marketing version, and the monotonic build behind it |
bundle_id | The binary's own identity, and what an APNs topic is checked against |
os_version | Verbatim, never normalised |
push_permission | allowed, denied, provisional or undetermined |
sdk_version | The Carillon SDK's own version |
opted_in | Your app's own opt-out switch, through optIn() and optOut() |
The SDK does not collect advertising identifiers, carrier, IP geolocation, screen metrics, battery state, or device model.
Registration and permission are separate
configure() starts token acquisition and registration without showing a permission prompt.
Call requestPermission() separately when your app should ask to display notifications.
Registration can succeed before permission is granted.
push_permission records the operating system permission. opted_in records your app's preference,
set with optIn() or optOut(). Opting in does not grant operating system permission.
Environments: sandbox and production
| Platform or build | Environment |
|---|---|
| iOS development-signed build or supported simulator | sandbox |
| iOS TestFlight or App Store build | production |
| Android | production |
The SDK detects the environment. APNs sandbox and production tokens are not interchangeable.
If registration fails, inspect debugInfo() and the platform registration error.
Token lifecycle
When APNs reports 410 Unregistered or FCM reports UNREGISTERED, Carillon invalidates the token
and stops sending to it. The device remains visible in the dashboard.
Disabling notification display is separate from token invalidation.
An invalidated device carries invalidated_at and invalidation_reason. The reason is
Superseded when the row lost its token to a newer registration of the same installation, and
otherwise the provider's own word, such as Unregistered or UNREGISTERED. Both are null on a
device that can still be sent to.
For APNs, the feedback timestamp must be later than the device's registration or re-registration. Older feedback does not invalidate a newly registered token.
Tags and opting out
setTags() replaces the complete tag map. Values can be strings, numbers, or booleans.
To remove a tag, send the map without that key. Audience filters
can match these values.
optOut() excludes the device from sending. Call optIn() to reverse the app-level opt-out.
Operating system notification permission is controlled separately by the user.
Deleting a device
Deletion needs a secret key with the devices:delete scope; a mobile key cannot delete.
| Call | Result |
|---|---|
DELETE /v1/devices/{id} | 204. Idempotent: deleting an unknown or already deleted ID also returns 204 |
DELETE /v1/devices?external_id=user-42 | 200 with { "deleted": n }, every device of that user in the app |
Only the device row is deleted. Its deliveries stay in campaign traces with their platform, and the presence rows that already counted the device toward this month's usage are kept, so usage already consumed remains billed. A token the SDK registers again after deletion creates a new device with a new ID.
Deleting is not opting out: to stop sending to an installation that still exists, use optOut()
or leave the token to be invalidated by the provider. Delete when the user is erased from your own
records, or to remove tokens imported by mistake.
Related pages
SDK overview · Audience filters · Register a device
Stable installation identity
Updated SDKs send the last confirmed device_id and a persisted random
installation_secret on registration. A matching proof lets the API replace the
push token on the same row, preserving attributes omitted from the request.
The server stores only a SHA-256 hash of the secret and never returns it.
An unknown or foreign ID, a missing/incorrect proof, or a different platform or
mode does not authorize reuse of the old row. If the replacement token already
belongs to a device in the same app/platform/mode, that row wins and the previous
row is invalidated. Subsequent registrations use the returned ID. A conflict with
another mode or platform returns 422 device_identity_conflict.
The SDK secret belongs to the installation. Reinstallation can create a new ID.
device_id alone is public context, not authentication. Integrations using older
SDKs continue to register by token.