Mobile Integration
Integrate React Native and other mobile apps with the Loop comms platform using the REST API for event firing, push notification delivery, and deep linking.
REST API for Events
Mobile apps interact with the comms platform via the REST API rather than importing @loop/contracts directly. All endpoints accept JSON and require a Bearer token.
Fire an Event
POST https://comms.loop.health/api/events
Content-Type: application/json
Authorization: Bearer <API_KEY>
{
"event": "lead.captured.v1",
"payload": {
"eventId": "550e8400-e29b-41d4-a716-446655440000",
"occurredAt": "2026-05-19T12:00:00Z",
"brandId": "your-brand-uuid",
"email": "user@example.com",
"source": "quiz_completion",
"attribution": {},
"personId": null
}
}Response Format
{
"ok": true,
"eventId": "550e8400-e29b-41d4-a716-446655440000",
"accepted": true
}Error responses follow the standard structure:
{
"ok": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "payload.email is required"
}
}Push Notification Setup
The comms platform delivers push notifications through APNs (iOS) and FCM (Android). Your mobile app needs to register device tokens.
1. Register the Device Token
After obtaining the push token from the OS, register it with the comms platform:
POST https://comms.loop.health/api/devices
Content-Type: application/json
Authorization: Bearer <USER_TOKEN>
{
"personId": "user-uuid",
"platform": "ios",
"token": "device-push-token",
"appVersion": "2.4.0"
}2. Handle Token Refresh
Tokens can change. Re-register on every app launch:
useEffect(() => {
const unsubscribe = messaging().onTokenRefresh(async (token) => {
await registerDeviceToken(token);
});
return unsubscribe;
}, []);3. Notification Payload Structure
Push notifications from the comms platform include:
| Field | Type | Description |
|---|---|---|
title | string | Notification title |
body | string | Notification body text |
data.deepLink | string | Deep link URL to open in-app |
data.compositionId | string | Template composition ID for tracking |
data.brandId | string | Brand identifier |
Deep Linking
The comms platform attaches deep links to push notifications, emails, and SMS messages. Configure your app to handle the loophealth:// scheme.
React Navigation Deep Link Config
const linking = {
prefixes: ['loophealth://', 'https://app.loop.health'],
config: {
screens: {
Protocol: 'protocol/:protocolId',
Labs: 'labs/:labId',
Chat: 'chat',
Profile: 'profile',
Supply: 'supply/:orderId',
},
},
};Handle Notification Tap
messaging().onNotificationOpenedApp((remoteMessage) => {
const deepLink = remoteMessage.data?.deepLink;
if (deepLink) {
Linking.openURL(deepLink);
}
});Offline Queueing
Mobile apps frequently lose connectivity. Queue events locally and flush when the network is available.
Recommended Approach
- Store events in local storage (AsyncStorage or MMKV) when offline
- Retry on reconnect using NetInfo listener
- Deduplicate using the
eventIdfield — the server ignores duplicateeventIdvalues
import NetInfo from '@react-native-community/netinfo';
const eventQueue: QueuedEvent[] = [];
async function fireEvent(event: string, payload: Record<string, unknown>) {
const entry = { event, payload, queuedAt: Date.now() };
const { isConnected } = await NetInfo.fetch();
if (isConnected) {
const ok = await sendToApi(entry);
if (!ok) eventQueue.push(entry);
} else {
eventQueue.push(entry);
}
}
NetInfo.addEventListener((state) => {
if (state.isConnected) flushQueue();
});Queue Limits
| Setting | Recommended Value |
|---|---|
| Max queue size | 500 events |
| Max event age | 72 hours |
| Flush batch size | 50 events |
| Retry delay | Exponential backoff (1s → 60s) |
Events older than 72 hours should be discarded — the server rejects stale events to prevent out-of-order processing.
Next Steps
- Event Catalog — Full list of event schemas
- Web App Integration — Web-specific integration guide
- Send a Transactional Email — End-to-end tutorial