Appearance
Sync project data
Keep a copy of a project's funnel users and their subscriptions up to date in your warehouse, CRM or internal tool. This guide uses an API key so the sync job reaches only the projects and data you allow.
Run the sync from a backend only. Never put a key in browser, funnel or mobile code.
1. Create an API key
In Organization Settings → API Keys → Create key, give the key a name, choose All projects or the projects to sync, and grant:
- Funnels · read (
funnels:read) - Experiments · read (
experiments:read), if you want experiments - Funnel users · read (
funnel_users:read) - Subscriptions · read (
subscriptions:read)
Copy the fg_key_… value once and store it in your backend secrets. See Authentication for how keys and scopes work.
2. Discover projects and funnels
List the projects the key can use, then the funnels of each project. Every request except GET /projects names its project with projectId.
sh
curl "https://sdk-api.funnelsgrove.com/integration/v1/projects" \
-H "Authorization: Bearer <api-key>"
curl "https://sdk-api.funnelsgrove.com/integration/v1/funnels?projectId=<project-id>" \
-H "Authorization: Bearer <api-key>"Store funnel id, slug and name: funnel-user records in a project-wide sync carry only the funnel id. Funnel updatedAt changes on rename, publish and production-URL changes, so you can refresh this table on a slow schedule.
List experiments the same way if you report on them. It returns variants and traffic splits, not results or per-user assignments.
3. Load funnel users incrementally
List funnel users without funnelId returns every funnel of the project in updatedAt order, oldest first. Add updatedSince to fetch only users changed since a moment, and follow nextCursor until it is null.
sh
curl "https://sdk-api.funnelsgrove.com/integration/v1/funnel-users/list?projectId=<project-id>&updatedSince=2026-10-20T00:00:00Z&limit=100" \
-H "Authorization: Bearer <api-key>"sh
curl "https://sdk-api.funnelsgrove.com/integration/v1/funnel-users/list?projectId=<project-id>&updatedSince=2026-10-20T00:00:00Z&limit=100&cursorUpdatedAt=2026-10-20T10:00:00.123456%2B00:00&cursorId=<funnel-user-id>" \
-H "Authorization: Bearer <api-key>"Each item is a funnel user: identity, answers, metadata, UTM attribution and subscription status. Pages hold up to 100 users. Encode + in timestamps as %2B.
A user's updatedAt changes when their profile, answers, email or login change, and after every payment, refund and subscription change. Chargebacks do not change it. Background maintenance can also change it, so expect some users to repeat.
4. Load subscriptions incrementally
List subscriptions works the same way: updatedSince, nextCursor, oldest first. Join each subscription to its user with funnelUserId. A cancellation, renewal or status change moves the subscription into your next updatedSince window.
sh
curl "https://sdk-api.funnelsgrove.com/integration/v1/subscriptions/list?projectId=<project-id>&updatedSince=2026-10-20T00:00:00Z&limit=100" \
-H "Authorization: Bearer <api-key>"5. Run the loop
- For users and for subscriptions, request pages until
nextCursorisnull, upserting each item byid. - Store the largest
updatedAtyou processed for each list. - Start the next run a few minutes before it. Timestamps are taken when a write starts, so a slow write can commit with an earlier
updatedAtthan a faster one you already saw. - De-duplicate by
id; the overlap and background maintenance make repeats normal.
The first run, without updatedSince, walks the whole project.
Look up one user
To refresh a single record, get the funnel user by user_id, email or funnelUserId:
sh
curl "https://sdk-api.funnelsgrove.com/integration/v1/funnel-users?projectId=<project-id>&funnelId=<funnel-id>&user_id=<user-id>" \
-H "Authorization: Bearer <api-key>"Limits and errors
The API allows 120 requests per minute per IP address; on 429, wait for Retry-After. A 403 means the key lacks a scope or the project is outside its Project Access, and a 400 means projectId is missing. See Errors.
To react to changes in real time instead of polling, receive project webhooks.