/activity
POSTSDK heartbeat endpoint. Reports foreground engagement for time-in-app analytics.
Overview#
This endpoint is called automatically by the SDK while the app is in the foreground (every 5 minutes by default). Each accepted call increments the per-install, per-day engagement count and records which hour of the day the app was active. This powers the Time in App metric in your analytics dashboard.
The SDK handles this automatically via Mobana.init(). You do not need to call this endpoint directly unless you are building a custom integration.
Endpoint#
POST https://YOUR_APP_ID.mobana.ai/activityWhen using a custom endpoint, the SDK calls {your-endpoint}/activity instead. Make sure your reverse proxy forwards /activity alongside the other SDK paths.
Authentication#
Requires a valid X-App-Key header. The app key is available in your Dashboard under App Settings → Integration. Invalid or missing keys return 401 Unauthorized.
Request#
POST https://YOUR_APP_ID.mobana.ai/activity
Content-Type: application/json
X-App-Key: YOUR_APP_KEY
{
"installId": "520e8400-c466-a554-40e0-0",
"timestamp": 1706745600000
}| Parameter | Type | Description |
|---|---|---|
installIdRequired | string | Unique ID for this install — the same value used with /find and /conversion. Maximum 36 characters. |
timestamp | number | Event time as epoch milliseconds (e.g., Date.now()). Used to assign the heartbeat to the correct UTC day and hour. Future timestamps are clamped to the server's current time to handle clock skew. Defaults to server time if omitted. |
Response#
Heartbeat accepted
{
"success": true
}Heartbeat debounced (within cooldown window)
{
"success": true,
"debounced": true
}| Property | Type | Description |
|---|---|---|
success | boolean | Always true for 200 responses. |
debounced | boolean | Present and true when the heartbeat was dropped because a previous one from the same install was accepted within the debounce window (4 minutes). The SDK can safely ignore this field. |
Debounce Semantics#
To prevent inflated engagement numbers and reduce database writes, the server applies a Redis-backed debounce per (installId, day):
- Cooldown window: 4 minutes (slightly shorter than the SDK's 5-minute heartbeat interval so on-time pings always pass).
- Effect: At most ~12 DB writes per active user per hour, regardless of how often the app calls this endpoint.
- Redis fallback: If Redis is unavailable, the debounce is skipped and the DB upsert runs directly. The upsert is idempotent, so counts may be slightly inflated during an outage but no data is lost.
Debounce constants are defined in src/lib/activity/constants.ts: HEARTBEAT_INTERVAL_MS (5 min) and HEARTBEAT_DEBOUNCE_SECONDS (240 s).
Silent-Success Pattern#
Like /conversion, this endpoint follows the silent-success pattern: every code path returns 200 { success: true } unless app-key authentication fails. Invalid installId values (wrong type, too long) are silently ignored. This ensures a flaky heartbeat never surfaces an error to the user.
CORS#
CORS is handled automatically. The endpoint responds to OPTIONS preflight requests with 204 and the standard Mobana CORS headers (including Access-Control-Allow-Headers: X-App-Key). The proxy diagnostic tool uses this OPTIONS fingerprint to verify that your reverse proxy forwards /activity correctly.