Subscriptions
This guide explains how to work with device subscriptions for push notifications in the Unified Order Service (UOS) API.
What are Device Subscriptions?
Device subscriptions in the UOS system manage Firebase Cloud Messaging (FCM) device tokens for sending push notifications to mobile applications. These subscriptions:
- Link FCM device tokens to specific places
- Enable real-time notifications for order status changes
- Support timeslot monitoring and delivery alerts
- Allow automatic cleanup of invalid or expired tokens
FCM Device Tokens
FCM device tokens are unique identifiers that Firebase uses to send push notifications to specific app installations. Key characteristics:
- Unique per installation: Each app installation has its own token
- Can change: Tokens may refresh when apps are restored, reinstalled, or updated
- Platform-specific: Different tokens for iOS and Android versions of the same app
- Temporary: Tokens can become invalid if the app is uninstalled
Managing Device Subscriptions
Registering a Device
To register a device for push notifications, send a PUT request to store the FCM token:
curl -X PUT "https://api.uos.example.com/dts/places/1ee68c4e-7008-4227-a92d-e1b13ac64f30/subscriptions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"device_token": "eGCgkKMKFHQ:APA91bEhSO-XOvT8..."
}'
Updating a Token
When your app detects that the FCM token has been refreshed, update the subscription:
curl -X PUT "https://api.uos.example.com/dts/places/1ee68c4e-7008-4227-a92d-e1b13ac64f30/subscriptions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"device_token": "fXYzABC123DEF:APA91bNewTokenValue..."
}'
Removing a Subscription
When a user logs out or disables notifications, remove the device subscription:
curl -X DELETE "https://api.uos.example.com/dts/places/1ee68c4e-7008-4227-a92d-e1b13ac64f30/subscriptions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"device_token": "eGCgkKMKFHQ:APA91bEhSO-XOvT8..."
}'
Integration Patterns
Mobile App Integration
1. On App Launch
// Example JavaScript/React Native code
import messaging from '@react-native-firebase/messaging';
const requestPermission = async () => {
const authStatus = await messaging().requestPermission();
const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
const token = await messaging().getToken();
await registerDeviceToken(token, placeId);
}
};
2. Token Refresh Handling
// Listen for token refresh
messaging().onTokenRefresh(token => {
registerDeviceToken(token, placeId);
});
const registerDeviceToken = async (token, placeId) => {
try {
const response = await fetch(`/dts/places/${placeId}/subscriptions`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ device_token: token })
});
if (response.ok) {
console.log('Device registered for notifications');
}
} catch (error) {
console.error('Failed to register device:', error);
}
};
3. User Logout
const logout = async () => {
const token = await messaging().getToken();
// Remove device subscription
await fetch(`/dts/places/${placeId}/subscriptions`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ device_token: token })
});
// Clear local session
clearUserSession();
};
Web Application Integration
1. Service Worker Registration
// Register service worker and get FCM token
if ('serviceWorker' in navigator) {
const registration = await navigator.serviceWorker.register('/sw.js');
const token = await getToken(messaging, {
vapidKey: 'your-vapid-key',
serviceWorkerRegistration: registration
});
if (token) {
await registerDeviceToken(token, placeId);
}
}
2. Token Management
// Handle token refresh in web apps
onMessage(messaging, (payload) => {
console.log('Message received:', payload);
showNotification(payload);
});
// Monitor token changes
onTokenRefresh(messaging, (token) => {
registerDeviceToken(token, placeId);
});
Notification Types
Device subscriptions will receive notifications for various order events:
Order Status Changes
- Order created
- Status updated (picking, picked, shipped, etc.)
- Order completed
- Order cancelled
Timeslot Monitoring
- Delivery window approaching (2:00 PM notification)
- Reminder notifications (2:15, 2:30, 2:45 PM if unpicked)
- Urgent alerts for delayed orders
System Notifications
- Service alerts
- Maintenance notifications
Best Practices
Token Management
- Refresh regularly: Check for token updates on app launch
- Handle failures: Implement retry logic for network failures
- Clean up: Remove tokens when users log out or uninstall
Error Handling
- Invalid tokens: Remove subscriptions for invalid or expired tokens
- Place validation: Ensure the place exists before registering
- Rate limiting: Respect API rate limits when updating tokens
Privacy and Permissions
- Request permission: Always ask users before registering for notifications
- Opt-out support: Provide easy ways to disable notifications
- Transparency: Explain what notifications users will receive
Security Considerations
Token Protection
- FCM tokens are sensitive and should be treated securely
- Tokens should only be sent over HTTPS
- Don't log tokens in plain text
API Key Security
- Use API keys with appropriate scopes
- Implement proper authentication in your app
- Rotate API keys regularly
Response Format
The DTS subscription endpoints return structured responses in the following format:
{
"status": 200,
"responseType": "success",
"message": {
"message": "Device subscription created/updated successfully",
"error": null,
"data": {
"place_id": "1ee68c4e-7008-4227-a92d-e1b13ac64f30",
"device_token": "eGCgkKMKFHQ:APA91bEhSO-XOvT8..."
},
"extra": null
}
}
Response Fields
status: HTTP status coderesponseType: Response type ("success" or "error")message.message: Human-readable messagemessage.error: Error details (null on success)message.data: Response data containingplace_idanddevice_tokenmessage.extra: Additional metadata (null for subscriptions)
Troubleshooting
Common Issues
Device not receiving notifications:
- Check if the device token is correctly registered
- Verify the place ID exists and is accessible
- Ensure FCM is properly configured in your app
- Check if notifications are enabled on the device
Token registration failing:
- Validate the FCM token format
- Confirm the place ID is a valid UUID
- Check API key permissions
- Verify network connectivity
Duplicate notifications:
- Ensure proper cleanup when tokens refresh
- Check for multiple app installations
- Verify subscription uniqueness logic
Testing Subscriptions
Manual Testing:
# Register a test device
curl -X PUT "https://api.uos.example.com/dts/places/test-place-id/subscriptions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"device_token": "test-token-123"
}'
# Verify registration (check logs)
# Create a test order to trigger notifications
# Confirm notifications are received on the device
Automated Testing:
- Include subscription management in your integration tests
- Mock FCM token generation for unit tests
- Test token refresh scenarios
- Verify cleanup on user logout
Example Workflow
Here's a complete example of integrating device subscriptions:
# 1. User opens app and grants notification permission
curl -X PUT "https://api.uos.example.com/dts/places/1ee68c4e-7008-4227-a92d-e1b13ac64f30/subscriptions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"device_token": "eGCgkKMKFHQ:APA91bEhSO-XOvT8..."
}'
# Response:
# {
# "status": 200,
# "responseType": "success",
# "message": {
# "message": "Device subscription created/updated successfully",
# "error": null,
# "data": {
# "place_id": "1ee68c4e-7008-4227-a92d-e1b13ac64f30",
# "device_token": "eGCgkKMKFHQ:APA91bEhSO-XOvT8..."
# },
# "extra": null
# }
# }
# 2. Create an order with timeslot (triggers notifications)
curl -X POST "https://api.uos.example.com/v1/orders" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"place_id": "1ee68c4e-7008-4227-a92d-e1b13ac64f30",
"delivery_window": {
"start": "2025-07-07T14:00:00Z",
"end": "2025-07-07T16:00:00Z"
}
}'
# 3. Device receives notifications:
# - Order created notification (immediate)
# - Timeslot notification at 2:00 PM
# - Reminder notifications if not picked
# 4. User logs out
curl -X DELETE "https://api.uos.example.com/dts/places/1ee68c4e-7008-4227-a92d-e1b13ac64f30/subscriptions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"device_token": "eGCgkKMKFHQ:APA91bEhSO-XOvT8..."
}'
# Response:
# {
# "status": 200,
# "responseType": "success",
# "message": {
# "message": "Device subscription deleted successfully",
# "error": null,
# "data": {
# "place_id": "1ee68c4e-7008-4227-a92d-e1b13ac64f30",
# "device_token": "eGCgkKMKFHQ:APA91bEhSO-XOvT8..."
# },
# "extra": null
# }
# }
This workflow ensures users receive timely notifications while maintaining proper subscription management throughout the app lifecycle.