Devices API
Register and manage device tokens for push notifications
Overview
The Devices API allows you to register and manage device tokens for push notifications. When users install your mobile app, you register their device token with Flameup to enable push messaging. Web push support is coming soon.
devices:write for all device operations.Supported Platforms
Flameup supports push notifications on three platforms:
iOS
Apple Push Notification service (APNs) via Firebase Cloud Messaging
Android
Firebase Cloud Messaging (FCM) for Android devices
Web (Coming Soon)
Web Push API via Firebase Cloud Messaging - Coming Soon...
Device Token Object
A device token in Flameup has the following structure:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"workspace_id": "ws_abc123",
"person_id": "550e8400-e29b-41d4-a716-446655440001",
"device_token": "fMhT8K9x...(FCM token)",
"platform": "ios",
"device_name": "iPhone 15 Pro",
"device_model": "iPhone16,1",
"os_version": "17.2",
"app_version": "2.1.0",
"is_active": true,
"is_valid": true,
"last_used_at": "2024-01-20T14:45:00Z",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T14:45:00Z"
}
Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | FCM/APNs token from the device |
platform | string | Yes | ios or android (web coming soon) |
device_name | string | No | Human-readable device name |
device_model | string | No | Device model identifier |
os_version | string | No | Operating system version |
app_version | string | No | Your app's version |
person_id is passed in the URL path, not in the request body.Register a Device
Register a device token to enable push notifications for a user.
Endpoint: POST /api/v1/people/{person_id}/devices
// After obtaining FCM token in your iOS app
async function registerIOSDevice(personId, fcmToken, deviceInfo) {
const response = await fetch(
`https://api.flameup.ai/api/v1/people/${personId}/devices`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({
token: fcmToken,
platform: 'ios',
device_name: deviceInfo.name, // e.g., "John's iPhone"
device_model: deviceInfo.model, // e.g., "iPhone16,1"
os_version: deviceInfo.osVersion, // e.g., "17.2"
app_version: deviceInfo.appVersion // e.g., "2.1.0"
})
}
);
return response.json();
}
Swift Example (getting the FCM token):
import FirebaseMessaging
Messaging.messaging().token { token, error in
if let token = token {
// Send this token to your backend
registerDevice(fcmToken: token)
}
}
// After obtaining FCM token in your Android app
async function registerAndroidDevice(personId, fcmToken, deviceInfo) {
const response = await fetch(
`https://api.flameup.ai/api/v1/people/${personId}/devices`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({
token: fcmToken,
platform: 'android',
device_name: deviceInfo.name,
device_model: deviceInfo.model, // e.g., "Pixel 8 Pro"
os_version: deviceInfo.osVersion, // e.g., "14"
app_version: deviceInfo.appVersion
})
}
);
return response.json();
}
Kotlin Example (getting the FCM token):
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
val token = task.result
// Send this token to your backend
registerDevice(fcmToken = token)
}
}
// After obtaining FCM token in your web app
async function registerWebDevice(personId, fcmToken) {
const response = await fetch(
`https://api.flameup.ai/api/v1/people/${personId}/devices`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({
token: fcmToken,
platform: 'web',
device_name: navigator.userAgent.includes('Chrome')
? 'Chrome Browser'
: 'Web Browser',
os_version: navigator.platform,
app_version: '1.0.0'
})
}
);
return response.json();
}
Web Example (getting the FCM token):
import { getToken } from 'firebase/messaging';
const token = await getToken(messaging, {
vapidKey: 'your-vapid-key'
});
// Send this token to your backend
await registerWebDevice(currentUserId, token);
curl -X POST "https://api.flameup.ai/api/v1/people/{person_id}/devices" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{
"token": "fMhT8K9x...your_fcm_token",
"platform": "ios",
"device_name": "iPhone 15 Pro",
"device_model": "iPhone16,1",
"os_version": "17.2",
"app_version": "2.1.0"
}'
response = requests.post(
f'https://api.flameup.ai/api/v1/people/{person_id}/devices',
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {API_KEY}'
},
json={
'token': fcm_token,
'platform': 'ios',
'device_name': 'iPhone 15 Pro',
'device_model': 'iPhone16,1',
'os_version': '17.2',
'app_version': '2.1.0'
}
)
device = response.json()
Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"person_id": "550e8400-e29b-41d4-a716-446655440001",
"device_token": "fMhT8K9x...",
"platform": "ios",
"is_active": true,
"is_valid": true,
"created_at": "2024-01-15T10:30:00Z"
}
List Devices
Retrieve all devices for a person.
Endpoint: GET /api/v1/people/{person_id}/devices
Query Parameters
| Parameter | Type | Description |
|---|---|---|
platform | string | Filter by platform: ios, android (web coming soon) |
is_active | boolean | Filter by active status |
limit | integer | Number of results (default 50, max 100) |
offset | integer | Pagination offset |
// Get all devices for a user
const response = await fetch(
`https://api.flameup.ai/api/v1/people/${personId}/devices`,
{
headers: {
'Authorization': `Bearer ${API_KEY}`
}
}
);
const { devices } = await response.json();
console.log(`User has ${devices.length} registered devices`);
response = requests.get(
f'https://api.flameup.ai/api/v1/people/{person_id}/devices',
headers={'Authorization': f'Bearer {API_KEY}'}
)
devices = response.json()['devices']
curl "https://api.flameup.ai/api/v1/people/{person_id}/devices" \
-H "Authorization: Bearer your_api_key"
Update a Device
Update device information (e.g., when the app version changes).
Simply call the register endpoint again with the same token and updated fields:
// Re-register with updated info
const response = await fetch(
`https://api.flameup.ai/api/v1/people/${personId}/devices`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({
token: existingToken,
platform: 'ios',
app_version: '2.2.0',
os_version: '17.3'
})
}
);
# Re-register with updated info
response = requests.post(
f'https://api.flameup.ai/api/v1/people/{person_id}/devices',
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {API_KEY}'
},
json={
'token': existing_token,
'platform': 'ios',
'app_version': '2.2.0',
'os_version': '17.3'
}
)
curl -X POST "https://api.flameup.ai/api/v1/people/{person_id}/devices" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{"token": "existing_fcm_token", "platform": "ios", "app_version": "2.2.0", "os_version": "17.3"}'
Delete a Device
Remove a device token (e.g., when user logs out or uninstalls).
Endpoint: DELETE /api/v1/people/{person_id}/devices/{token}
const response = await fetch(
`https://api.flameup.ai/api/v1/people/${personId}/devices/${encodeURIComponent(deviceToken)}`,
{
method: 'DELETE',
headers: {
'Authorization': `Bearer ${API_KEY}`
}
}
);
if (response.ok) {
console.log('Device unregistered');
}
import urllib.parse
response = requests.delete(
f'https://api.flameup.ai/api/v1/people/{person_id}/devices/{urllib.parse.quote(device_token, safe="")}',
headers={'Authorization': f'Bearer {API_KEY}'}
)
curl -X DELETE "https://api.flameup.ai/api/v1/people/{person_id}/devices/{device_token}" \
-H "Authorization: Bearer your_api_key"
Token Lifecycle
Device tokens have a lifecycle that Flameup manages automatically:
Registration
Token is registered when user enables notifications or installs the app.
is_active: trueis_valid: true
Active Use
Token is used for push delivery. last_used_at is updated with each use.
Token Refresh
FCM may issue a new token. Re-register with the new token; Flameup deduplicates by device.
Invalidation
If push delivery fails (uninstall, revoked permissions), token is marked:
is_valid: falseis_active: false
Handling Token Refresh
FCM tokens can change. Handle token refresh in your app:
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging,
didReceiveRegistrationToken fcmToken: String?) {
guard let token = fcmToken else { return }
// Re-register with Flameup
FlameupAPI.registerDevice(token: token)
}
}
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
// Re-register with Flameup
FlameupAPI.registerDevice(token)
}
}
import { onMessage, getToken } from 'firebase/messaging';
// Listen for token refresh
navigator.serviceWorker.addEventListener('message', async (event) => {
if (event.data.type === 'TOKEN_REFRESH') {
const newToken = await getToken(messaging);
await registerDevice(newToken);
}
});
Best Practices
Register the device token after user login to associate it with the correct person:
async function onUserLogin(userId) {
const fcmToken = await getFCMToken();
const person = await flare.identifyUser(userId);
await flare.registerDevice(person.id, fcmToken);
}
Troubleshooting
| Issue | Solution |
|---|---|
| Token not registered | Verify person_id exists and token is valid |
| Wrong platform | Ensure platform matches the device (ios/android) |
| Invalid token | Token may have expired; request a fresh token from FCM |
| User not receiving | Check is_active and is_valid are both true |
| Notification blocked | User may have disabled notifications in device settings |
Last updated today