# Facebook Lead Ads API: Retrieve Leads and Sync a CRM

How to get leads from the Facebook Lead Ads API: the leads edge on forms and ads, leads_retrieval, leadgen webhooks, the 90-day window, and CRM sync patterns.

Canonical page: https://www.tryadeli.com/blog/facebook-lead-ads-api
Last updated: 2026-10-26

By Mika Reyes, Co-founder, Adeli. Published 2026-10-26.

## 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](https://www.tryadeli.com/blog/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](https://developers.facebook.com/docs/marketing-api/guides/lead-ads/retrieving):

| 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](https://developers.facebook.com/ads/blog/post/2018/07/02/lead-ads-retrieval/) 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:

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

Then fetch the answers:

```bash
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.

```bash
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](https://www.facebook.com/business/help/734933888443065) 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](https://www.jonloomer.com/meta-ads-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](https://developers.facebook.com/tools/lead-ads-testing) 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](https://www.tryadeli.com/docs/api/ads/list-leads):

```bash
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](https://www.tryadeli.com/blog/facebook-ads-api-create-campaign) that drive the leads and [publishes the posts](https://www.tryadeli.com/social-media-posting-api) they promote. [Pricing](https://www.tryadeli.com/pricing) is per customer profile, so it follows how you bill.

## 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.

## Related Adeli pages

- [Social Media API for Vertical SaaS Platforms](https://www.tryadeli.com/use-cases/vertical-saas.md): Give your small-business customers posting, scheduling, analytics, inbox, and Meta ads inside your vertical SaaS, through one API.
- [Social Media and Ads API for AI Marketing Platforms](https://www.tryadeli.com/use-cases/ai-marketing-platforms.md): Run posting, analytics, inbox, and Meta ads for your customers' accounts through one API, without months of platform reviews.
- [All posts on the Adeli blog](https://www.tryadeli.com/blog.md)

## About the author

Mika Reyes is the CEO behind Adeli and a tech and AI content creator. She was previously co-founder and CEO of Parallax, which was acquired by Phantom, and a product lead at LinkedIn. She is a Forbes 30 Under 30 honoree.
