Guide
Sync leads to your CRM
Pull the people a flipbook captured — through lead forms, gated access or CTA submissions — and keep them flowing into your own systems on a schedule.
Before you start
- An API key with the
exports:readandsubscribers:readscopes. - The reader-level analytics in the last step need the Company plan. The lead export itself does not.
- 1
Decide between a pull and a push
There are two ways to get leads out. Exports are a pull: you ask for a flipbook's leads and get a file back — simplest to schedule, and the right choice for a nightly CRM sync.
Webhooks are a push: Flipbooker calls you the moment someone submits a form. Use those when a salesperson needs to follow up within minutes rather than overnight.
Most teams run both — webhooks for speed, a nightly export to backfill anything a failed delivery missed.
- 2
Export a flipbook's leads
Ask for the leads captured by one flipbook. Unlike the analytics exports it carries no plan-tier requirement — the
exports:readscope is the only thing checked.The response is a file download, not JSON — write it straight to disk rather than parsing it as an API envelope.
GET /exports/books/{bookId}/leadscurl https://app.flipbooker.com/api/v1/exports/books/4821/leads \ -H "Authorization: Bearer $FLIPBOOKER_API_KEY" \ -o leads-4821.csv - 3
Or read subscribers as JSON
If you would rather work with structured data than a file,
GET /subscribersreturns everyone across the workspace's flipbooks — including readers added by email gating, not just form submissions.It is cursor-paginated, so follow
meta.next_cursoruntilhas_moreis false.GET /subscriberscurl -G https://app.flipbooker.com/api/v1/subscribers \ -H "Authorization: Bearer $FLIPBOOKER_API_KEY" \ -d limit=100 - 4
Sync incrementally, not from scratch
Re-importing every lead each night will create duplicates in most CRMs. Keep a high-water mark of the last record you processed and upsert on email address.
The snippet below walks every page, then hands only the new records to your CRM client.
Nightly syncconst KEY = process.env.FLIPBOOKER_API_KEY let cursor = null const fresh = [] do { const url = new URL('https://app.flipbooker.com/api/v1/subscribers') url.searchParams.set('limit', '100') if (cursor) url.searchParams.set('cursor', cursor) const res = await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } }) if (!res.ok) throw new Error(`Flipbooker returned ${res.status}`) const { data, meta } = await res.json() for (const person of data) { if (person.created_at > lastSyncedAt) fresh.push(person) } cursor = meta?.has_more ? meta.next_cursor : null } while (cursor) // Upsert on email so a re-run is harmless. await crm.upsertContacts(fresh, { matchOn: 'email' })Watch the rate limitA full sync is a burst of requests against one endpoint, which is capped at 100 per minute. Page with limit=100 and back off on a 429 rather than running the loop flat out. - 5
Prove where a lead came from
Sales will ask which document produced a lead. Pair the export with
GET /analytics/readersfor the samebook_idto attach engagement — how long they read, how far they got — to each contact.For campaign-level attribution, create a tracked link per channel and filter analytics by
tracked_link_id.GET /analytics/readerscurl -G https://app.flipbooker.com/api/v1/analytics/readers \ -H "Authorization: Bearer $FLIPBOOKER_API_KEY" \ -d book_id=4821 \ -d sort=engagement