Facebook Lead Ads API: Retrieve Leads and Sync a CRM

By Mika ReyesPublished 5 min read

The short answer

The Facebook Lead Ads API returns instant form submissions two ways: a leadgen webhook on the Page that sends each new lead's ID in real time, and bulk reads from GET /{form-id}/leads or /{ad-id}/leads. Both need the leads_retrieval permission. Meta keeps lead data for 90 days, so sync it to a CRM promptly. Adeli lists a Page's lead forms and their submissions in one call.

The Facebook Lead Ads API gives you instant form submissions in two ways: a leadgen webhook that notifies you the moment someone submits a form, and bulk reads from the leads edge on a form (GET /{form-id}/leads) or an ad (GET /{ad-id}/leads). Both need the leads_retrieval permission, and Meta keeps lead data for 90 days, so the job is to get each lead into a CRM quickly.

This guide covers the permissions, both retrieval methods, and the sync patterns that keep a CRM complete. It's written for developers at platforms that run lead ads for their customers, such as real estate or home services software. It's part of our Meta Ads API series.

What do you need before you start?

Lead retrieval needs a Page or user token from someone who can advertise on both the Page and the ad account, plus five permissions. From Meta's retrieving leads guide:

Permission Why
leads_retrieval Read the lead's answers. Required for every read.
ads_management Read ad fields such as ad_id and campaign_id
pages_manage_ads Manage ads for the Page
pages_read_engagement Read the Page's content and metadata
pages_show_list List the Pages the person manages
pages_manage_metadata Subscribe your app to the Page's webhooks (webhooks only)

Leads Access Manager can override Page roles. If a business admin has customized lead access, a Page admin without it gets nothing back. When a customer's leads come back empty, check Leads Access Manager first.

leads_retrieval arrived on July 2, 2018. Before that, Meta's announcement notes, "you could access the Lead Retrieval API with only the manage_pages permission." Older tutorials still describe that setup.

How do I get leads in real time with webhooks?

Subscribe your app to the Page's leadgen webhook field, then fetch each lead by the leadgen_id in the notification. The webhook carries IDs, not answers, so every notification is followed by one read.

  1. Set up a webhook endpoint in your app's Webhooks product, choose the Page object, and subscribe to the leadgen field.
  2. Install your app on each customer's Page with POST /{page-id}/subscribed_apps, using that Page's access token. A long-lived Page token keeps this working without re-authentication.
  3. Read the lead when a notification arrives.

A notification's value looks like this:

{
  "leadgen_id": 123123123123,
  "page_id": 123123123,
  "form_id": 12312312312,
  "adgroup_id": 12312312312,
  "ad_id": 12312312312,
  "created_time": 1440120384
}

Then fetch the answers:

curl -G "https://graph.facebook.com/v26.0/$LEADGEN_ID" \
  --data-urlencode "fields=created_time,ad_id,form_id,field_data" \
  --data-urlencode "access_token=$PAGE_TOKEN"

field_data is a list of { "name": "email", "values": ["..."] } objects, one per question. Meta says real-time pings can arrive up to a few minutes after the submission. Notifications only arrive if the Page hasn't disabled the App platform in its settings.

How do I bulk read leads from a form or an ad?

Call the leads edge on a form ID or an ad ID. A form can be reused by many ads, so the form edge can return far more leads than any one ad using it.

curl -G "https://graph.facebook.com/v26.0/$FORM_ID/leads" \
  --data-urlencode "fields=created_time,id,ad_id,form_id,field_data" \
  --data-urlencode 'filtering=[{"field":"time_created","operator":"GREATER_THAN","value":1761945743}]' \
  --data-urlencode "access_token=$ACCESS_TOKEN"
  • Filter by time with time_created and GREATER_THAN, GREATER_THAN_OR_EQUAL, or LESS_THAN, using Unix timestamps. This is how an incremental sync asks only for new leads.
  • Page with cursors. Results come back in pages with before and after cursors.
  • Read disclaimer checkboxes separately. Optional custom disclaimer answers aren't in field_data; request custom_disclaimer_responses on the lead.
  • Mind the rate limit. Meta allows 200 × 24 × the number of leads the Page created in the past 90 days, per 24 hours.

How long are Facebook leads available?

Meta keeps lead data available for 90 days after submission. Meta's Business Help Center page on downloading leads data says leads older than that can't be downloaded. For your integration, that turns a delayed sync into lost data:

  • A broken webhook for a weekend is recoverable with a bulk read.
  • A broken webhook for a quarter is not.
  • A customer who connects late only gets the last 90 days of history.

Meta's retrieval guide also offers a CSV export, GET https://www.facebook.com/ads/lead_gen/export_csv/ with from_date and to_date, but it's built for people, not syncs. The leads edge is the one to automate.

How should I sync Facebook leads to a CRM?

Use the webhook for speed and a scheduled bulk read as a safety net, and key every write on the lead ID. A lead that waits for a manual import waits to hear from your customer:

"Without this auto-syncing, leads will be forced to wait to hear from you until you've manually added them." Jon Loomer, Meta ads consultant, How to Use Meta Ads for Lead Generation (July 21, 2026)

A sync pattern for platforms:

  1. Webhook first. On each leadgen notification, fetch the lead and upsert it in the CRM within seconds.
  2. Idempotent writes. Use the lead id as the CRM's external key. Webhooks can repeat, and your backfill will overlap with them.
  3. Scheduled backfill. Every hour or night, bulk read each active form with time_created greater than your last sync time, minus a margin. This catches missed or failed webhooks.
  4. Map by field name, not position. Customers edit forms. Map field_data by name, and store unmapped answers so nothing is dropped.
  5. Keep attribution. Store ad_id, form_id, and the campaign with the lead, so your customer can see which ad brought in which leads.
  6. Treat it as personal data. Lead answers are names, emails, and phone numbers. Encrypt them at rest and delete them when the customer disconnects.

To test the pipeline, create a lead with Meta's Lead Ads Testing Tool or POST /{form-id}/test_leads. Each form holds one test lead at a time.

Is there a faster way to do this?

Adeli lists a customer's lead forms and returns each form's submissions, with the campaign, ad set, and ad each lead came from, in one call. Adeli holds the Meta app and the leads_retrieval grant, so you skip App Review for it and per-Page token handling. The endpoint is lead forms and leads:

curl -G "https://app.tryadeli.com/api/v1/ads/leads" \
  -H "Authorization: Bearer $ADELI_API_KEY" \
  --data-urlencode "accountId=$ACCOUNT_ID" \
  --data-urlencode "formId=555666777888999"
  • Without formId, the response lists the connected Page's lead generation forms.
  • With formId, it returns that form's submissions: each lead's id, createdAt, fields, and the campaignName, adSetName, and adName.
  • Adeli doesn't store lead data. Submissions are read from Facebook when you ask for them and aren't retained after the response, so the copy in your CRM is the only one outside Meta.
  • A missing grant is explicit. A connection without leads_retrieval returns 403 ads_permission_required naming the missing scope.

Run it on a schedule per customer form and upsert by lead id, the same way as the backfill above. The same API key creates the campaigns that drive the leads and publishes the posts they promote. Pricing is per customer profile, so it follows how you bill.

faq

Frequently asked questions

How long does Facebook keep lead ads data?

Meta's Business Help Center says lead data is available to download for 90 days after someone submits the form. After that it can't be downloaded, so a CRM sync has to pick leads up well inside that window.

Why do some leads have no ad_id or campaign?

Meta's retrieval guide gives three reasons: the lead came from organic reach rather than an ad, it was submitted from an ad preview, or the person requesting the leads doesn't have advertiser access on the ad account. Test leads from Meta's testing tool are organic, so they never carry an ad ID.

How do I create a test lead for my integration?

Use Meta's Lead Ads Testing Tool or POST to the form's test_leads edge with a Page access token. Each form can hold one test lead at a time, so delete it before creating another. The testing tool doesn't work while your app is in development mode.

What is the rate limit for retrieving leads?

Meta allows 200 times 24 times the number of leads the Page created in the past 90 days, per 24 hours. A Page with 50 recent leads gets 240,000 calls a day, so the limit rarely binds unless you poll every form constantly.

Power your next project
with one ads & social media API

Give your users publishing, scheduling, and analytics through one integration your team can actually maintain.

Try with agents

Start with free credits. No credit card required.