Where
Settings→API & Integrations
Your role needs
Update access to Lead intake API
update-companies. Admin have it by default.Authenticated by a workspace API key, not by a signed-in session. Creating a key needs the same permission as the rest of the API settings tab.
How it behaves
Idempotency stops one call from running twice
Send anIdempotency-Key header on POST /leads or POST /leads/batch, and a retried call with the exact same body returns the stored response instead of running again. The reply carries an Idempotency-Replayed: true header so you can tell a fresh answer from a replayed one.
cURL
400 and invalid_idempotency_key. Your body is validated before the key is looked at, though, so a call that is both malformed and over-long comes back as a 422 about the body instead. The key is scoped to the API key that sent it: a second key reusing the exact same value, even inside the same workspace, is its own bucket and never collides with the first.
Reuse a key with a body that isn’t identical to the first call’s, and you get a 409 of its own, distinct from a duplicate-lead conflict. The whole request body is fingerprinted, not just the lead fields, so a second call under the same key with dry_run flipped counts as a different body and is rejected the same way.
Because the fingerprint covers the full body, you can’t preview a lead with
dry_run: true and then reuse the same Idempotency-Key to send it for real. The second call’s body differs from the first and is rejected. Use one key per real attempt.400 is memoized. An error is never stored, so retrying after one genuinely runs again rather than replaying the failure.
A replayed response skips the whole pipeline, not just the reply: no duplicate lookup, no tag creation, nothing queued a second time. A plain retry with no key usually lands on the same lead anyway: it matches the lead the first call created, on the same email, LinkedIn handle or phone, and the default update merges into it instead of creating a second row. What a key adds is that the retry changes nothing at all, rather than running that match again and merging into the same lead a second time. The stored response is kept for 24 hours; once it lapses, reusing the key runs the call for real again, as if it had never been sent.
Deduplication recognizes a person you already have
Before either endpoint creates or updates a lead, it looks for an existing one in your workspace, checking the strongest identifier first: any of the person’s own email addresses (email and emails[], never the company’s), then the profile handle inside linkedin_url, then a phone number. The match never looks outside the workspace the key belongs to, and a name is never part of it. Two people who happen to share one are two people, and merging them would be unrecoverable.
Phone matching compares trailing digits rather than the full string, so the same number spelled with and without a country code or a trunk prefix still matches; a number that reduces to fewer than 7 digits is skipped rather than risking a false match.
on_duplicate decides what happens once a match is found:
on_duplicate is a call-level switch, so on POST /leads/batch it applies to every row. A duplicate under error there fails only its own row: the call still answers 200, and the failed row carries the matched lead_id.
dry_run: true runs this same check for real, inside a transaction that always rolls back. A preview tells you honestly whether a call would have matched an existing lead, without writing anything.
Rate limits cap how often you can call
Every key gets a budget of 300 requests a minute, counted against the key itself, never the address the request came from. So an integration running on a shared or serverless host is measured on its own traffic alone. APOST /leads/batch call counts as one request against that budget whatever it carries (up to 100 leads in a single call), so batching a list is how you move it through fast, rather than looping single POST /leads calls one lead at a time.
Cross the limit and further calls are rejected until the window clears; what comes back is on the errors reference.
Limits
Related
POST /leads
The full request body and response envelope this page’s rules apply to.
POST /leads/batch
Send many leads in one call, and read the outcome of each row on its own.
Errors reference
Every status the API returns and what to change before you retry.