API · Devices
Register, update, identify and unsubscribe your app's devices.
Base: https://api.pushtifly.com. Every response uses { errCode, errMsg, data, meta }. Authentication and keys · Error catalog
- GET
/v1/devices - POST
/v1/devices - GET
/v1/devices/by-user/{externalUserId} - GET
/v1/web-push/key - GET
/v1/devices/{token} - PATCH
/v1/devices/{token} - DELETE
/v1/devices/{token} - POST
/v1/devices/{token}/identify - POST
/v1/devices/{token}/logout - PUT
/v1/devices/{token}/tags - POST
/v1/devices/{token}/topics/{topic} - DELETE
/v1/devices/{token}/topics/{topic} - POST
/v1/devices/{token}/pair
GET/v1/devices
List/search devices (sk_ with devices:read). Filters q, status, platform, externalUserId; paginated.
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
appId | query | string | |
q | query | string | |
status | query | "active" | "pending_credential" | "invalid" | "unsubscribed" | |
platform | query | "android" | "ios" | "web" | |
externalUserId | query | string | |
page | query | integer | |
perPage | query | integer |
Responses: 200403
curl -X GET "https://api.pushtifly.com/v1/devices" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY"POST/v1/devices
Register or update a device (upsert by token). pk_ or sk_ with devices:write.
Key: pk_ / sk_
The provider is detected from the token format (FCM or APNs). Huawei phones: provider "hms" with the Push Kit token.
Browsers: platform "web" and subscription
(PushSubscription.toJSON()); its endpoint acts as the token. Errors: 2004 platform not enabled in the app,
2005 token inconsistent with platform/provider, 2006 Expo token, 2012 time zone. If the app has no credential for
the provider, the device stays pending_credential (meta.warnings explains it) and becomes active once it is uploaded.
Body
| Field | Type | Description |
|---|---|---|
appId | string | |
token | string | FCM registration token, Firebase Installation ID (22 characters), APNs token (hexadecimal) or Huawei Push Kit token (with provider hms). Not sent on web: subscription is sent instead. · max. 512 characters |
platform | "android" | "ios" | "web" | |
provider | "fcm" | "apns" | "webpush" | "hms" | Optional: detected from the format. Required for Huawei (hms), whose token cannot be told apart by its format. |
subscription | object | Web only: the browser's PushSubscription.toJSON(). The endpoint must belong to a known Web Push service (https). |
subscription.endpoint | string | max. 512 characters |
subscription.keys | object | |
environment | "sandbox" | "production" | "auto" | |
framework | string | |
sdkName | string | |
sdkVersion | string | |
capabilities | "images" | "actions" | "open_tracking" | "foreground_display" | "deep_links" | "carousel"[] | |
externalUserId | string | |
language | string | |
timezone | string | |
country | string | |
appVersion | string | |
osVersion | string | |
deviceModel | string | |
notificationsEnabled | boolean | |
tags | object |
Responses: 200201422
curl -X POST "https://api.pushtifly.com/v1/devices" \
-H "Authorization: Bearer pk_test_YOUR_PUBLIC_KEY" \
-H "Content-Type: application/json" \
-d '{
"token": "DEVICE_FCM_OR_APNS_TOKEN",
"platform": "android",
"environment": "auto",
"externalUserId": "customer-123",
"language": "en",
"timezone": "America/New_York",
"appVersion": "2.4.0",
"notificationsEnabled": true,
"tags": {
"plan": "gold",
"city": "boston"
}
}'GET/v1/devices/by-user/{externalUserId}
Devices of an external user (sk_)
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
externalUserId* | path | string |
Responses: 200
curl -X GET "https://api.pushtifly.com/v1/devices/by-user/customer-123" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY"GET/v1/web-push/key
The app's public VAPID key (Web Push), for PushManager.subscribe(). pk_ or sk_; 5001 if the app has no keys
Key: pk_ / sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
appId | query | string |
Responses: 200422
curl -X GET "https://api.pushtifly.com/v1/web-push/key" \
-H "Authorization: Bearer pk_test_YOUR_PUBLIC_KEY"GET/v1/devices/{token}
Details (with tags and topics). sk_.
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string | URL-encoded token or the device id (required on web: the token is a URL) |
Responses: 200404
curl -X GET "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY"PATCH/v1/devices/{token}
Update attributes (language, time zone, versions, notificationsEnabled…)
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string | URL-encoded token or the device id (required on web: the token is a URL) |
Body
| Field | Type | Description |
|---|---|---|
appId | string | |
token | string | FCM registration token, Firebase Installation ID (22 characters), APNs token (hexadecimal) or Huawei Push Kit token (with provider hms). Not sent on web: subscription is sent instead. · max. 512 characters |
platform | "android" | "ios" | "web" | |
provider | "fcm" | "apns" | "webpush" | "hms" | Optional: detected from the format. Required for Huawei (hms), whose token cannot be told apart by its format. |
subscription | object | Web only: the browser's PushSubscription.toJSON(). The endpoint must belong to a known Web Push service (https). |
subscription.endpoint | string | max. 512 characters |
subscription.keys | object | |
environment | "sandbox" | "production" | "auto" | |
framework | string | |
sdkName | string | |
sdkVersion | string | |
capabilities | "images" | "actions" | "open_tracking" | "foreground_display" | "deep_links" | "carousel"[] | |
externalUserId | string | |
language | string | |
timezone | string | |
country | string | |
appVersion | string | |
osVersion | string | |
deviceModel | string | |
notificationsEnabled | boolean | |
tags | object |
Responses: 200
curl -X PATCH "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"language": "es",
"notificationsEnabled": false,
"tags": {
"plan": "platinum"
}
}'DELETE/v1/devices/{token}
Unsubscribe (status unsubscribed; registering again reactivates it)
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string | URL-encoded token or the device id (required on web: the token is a URL) |
Responses: 200
curl -X DELETE "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY"POST/v1/devices/{token}/identify
Link externalUserId
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string |
Body
| Field | Type | Description |
|---|---|---|
externalUserId* | string | max. 191 characters |
Responses: 200
curl -X POST "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN/identify" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalUserId": "customer-123"
}'POST/v1/devices/{token}/logout
Unlink externalUserId
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string |
Responses: 200
curl -X POST "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN/logout" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY"PUT/v1/devices/{token}/tags
Merge tags (null deletes a key) or replace them all with replace=true. Maximum 50.
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string |
Body
| Field | Type | Description |
|---|---|---|
tags | object | |
replace | boolean |
Responses: 200
curl -X PUT "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN/tags" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"tags": {
"plan": "gold",
"last_purchase": "2026-10-01"
}
}'POST/v1/devices/{token}/topics/{topic}
Subscribe to a topic (created if it doesn't exist)
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string | |
topic* | path | string |
Responses: 200
curl -X POST "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN/topics/offers" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY"DELETE/v1/devices/{token}/topics/{topic}
Unsubscribe
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string | |
topic* | path | string |
Responses: 200
curl -X DELETE "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN/topics/offers" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY"POST/v1/devices/{token}/pair
Mark as a test device with the 6-digit code from the panel (2008 if it is invalid or expired)
Key: sk_
Parameters
| Name | In | Type | Description |
|---|---|---|---|
token* | path | string |
Body
| Field | Type | Description |
|---|---|---|
code* | string |
Responses: 200422
curl -X POST "https://api.pushtifly.com/v1/devices/DEVICE_TOKEN/pair" \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "482913"
}'