Backfill historical data
Import an existing app's user history so Airhop's funnel, health, and alerts are accurate from day one.
If you already have users when you adopt Airhop, you can replay their history so the activation funnel, health scores, and lifecycle playbooks reflect what really happened — instead of starting from an empty slate and only learning about your users going forward.
Backfilling uses the same ingest API you already know. You just replay past identify and track calls with their original timestamps, and set a flag so Airhop imports the history quietly.
Two things that make it correct
1. Send the real timestamp
Every call takes a timestamp (ISO-8601). Airhop derives everything from it — when an event happened, when a user first and last did something, and when they crossed each milestone. Without it, a call is treated as happening now.
Backfilling runs server-side, not through the browser SDK. The SDK stamps timestamp as the current time (it can only describe what's happening live), so it can't carry history. Use the batch API from a script or job.
2. Import in the background with backfill
Set backfill: true on the request (or send the header X-Airhop-Backfill: 1). In this mode Airhop records your users' milestones and health, but does not fire playbooks or count billable outcomes for the imported history — so importing a year of activations won't send a year of welcome emails.
After the import: going live
The first time you send events without backfill, Airhop starts tracking you as live. For a short settling window after that (about a day), time-based playbooks — stalled, inactive, renewal, and health-drop nudges — hold their fire. This stops a brand-new install from immediately messaging every account that looks stalled or churned in your freshly-imported history, and gives your team a moment to review before Airhop reaches out.
So the order that works best is:
- Backfill your history with
backfill: true. - Go live — send new events as they happen, without the flag.
Recipe
Page through your history in batches (up to 5000 calls per batch), authenticating with your wk_... write key:
curl https://app.airhop.ai/ingest/v1/batch \
-H "Authorization: Bearer wk_your_write_key" \
-H "Content-Type: application/json" \
-d '{
"backfill": true,
"batch": [
{
"type": "identify",
"userId": "user_123",
"traits": { "email": "jo@acme.com", "name": "Jo Diaz", "plan": "pro" },
"timestamp": "2025-01-04T10:00:00Z",
"messageId": "bf-user_123-signup"
},
{
"type": "track",
"userId": "user_123",
"event": "project_created",
"timestamp": "2025-01-05T14:12:00Z",
"messageId": "bf-user_123-1"
}
]
}'A few practical notes:
- Give every call a stable
messageId. Ingestion is idempotent on the user, message id, and timestamp, so a batch that fails halfway can be safely re-sent — duplicates are ignored. - Ordering within a batch doesn't matter. Milestone timing is computed from the events themselves, not the order they arrive. Sending each user's events oldest-first across batches is a fine, simple approach.
- Identify your users too, not just their events — the
identifytraits (email, name, plan) are what make imported accounts recognizable and let health and outreach work.
Backfilling is safe to run more than once. If you're unsure how far back your data goes, start with the most recent few months (which drive current health and activation), then extend earlier if you want deeper funnel history.