Skip to main content

List Contact Devices

List every device a contact has registered, including revoked and expired ones.

Use this to answer support questions — "why didn't this customer get the notification?" — by checking device status, permission state, and whether the Arsel SDK is embedded.

Endpoint

GET /push/contacts/{contactId}/devices

Returns: 200 OK

Path Parameters

ParameterTypeDescription
contactIdstringArsel contact UUID

Query Parameters

ParameterTypeDefaultDescription
platformstringallFilter to android, ios, or web.
statusstringallFilter to ACTIVE, EXPIRED, REVOKED, or FAILED. Defaults to every status, revoked and expired included.
limitinteger20Items per page, 1–100.
afterstringReturn items after this id (exclusive).
beforestringReturn items before this id (exclusive).

See Pagination for how cursor paging works.

Headers

HeaderValueRequired
AuthorizationBearer <your-api-key>Yes

Response

{
"object": "list",
"has_more": false,
"data": [
{
"id": "01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a",
"installation_id": "install-abc123",
"platform": "android",
"vendor": "fcm",
"status": "ACTIVE",
"revoke_reason": null,
"device_token_masked": "fzXn…J3x9",
"enablement_status": "AUTHORIZED",
"sdk_enabled": true,
"sdk_version": "android/1.2.0",
"app_version": "3.4.1",
"device_model": "Pixel 8",
"device_timezone": "Asia/Riyadh",
"device_locale": "ar-SA",
"last_used_at": "2026-06-01T12:00:00.000Z",
"last_seen_at": "2026-06-01T12:00:00.000Z",
"created_at": "2026-05-20T09:14:00.000Z"
}
]
}
FieldTypeDescription
idstringDevice ID (UUIDv7)
installation_idstringThe natural key. Correlate on this across every push route.
platformstringandroid, ios, web
vendorstringfcm, apns, web_push
statusstringACTIVE, EXPIRED, REVOKED, FAILED
revoke_reasonstring | nulluser_opt_out, contact_opt_out, dead_token, or admin
device_token_maskedstring | nullFirst and last few characters only
enablement_statusstring | nullOS permission last reported by the device
sdk_enabledbooleanWhether the Arsel SDK is embedded on this device
sdk_versionstring | nulle.g. android/1.2.0
last_used_atstring | nullLast time Arsel sent to this device
last_seen_atstring | nullLast time the device checked in
The raw device token is never returned

device_token_masked shows only the first and last few characters. The full token is a sendable credential — anyone holding it and your Firebase project could push to that device — so Arsel never returns it, not even to the account that supplied it. Correlate on installation_id instead.

Reading revoke_reason

ValueMeaningReversible?
user_opt_outThe user opted out in your appNo — durable
contact_opt_outRevoked via Unregister DeviceNo — durable
dead_tokenThe transport rejected the token permanently (uninstall, ~270 days inactive, or the token belongs to a different Firebase sender)Yes — a successful re-register clears it
adminRevoked by Arsel staff

Examples

curl "https://api.arsel.sa/v1/push/contacts/01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a/devices?status=ACTIVE&limit=50" \
-H "Authorization: Bearer be_your_api_key"

Error Responses

{
"status_code": 404,
"name": "not_found",
"message": "Contact not found"
}