Skip to main content
Leads are phone numbers (with optional metadata) attached to a campaign. All leads are automatically scrubbed against the TRAI DNC registry at ingestion time — leads flagged as DND are marked but not rejected.
One endpoint, two spellings. Every request field below accepts our canonical name and the common CRM aliases in the Aliases column — you don’t need to rename columns before pushing. The Salesforce lead push guide shows the same endpoint using the CRM spellings (lead_id / first_name / mobile); those pages are not describing two different APIs.If a request carries both spellings of one field, the canonical name wins (name beats first_name).Aliases apply to the request only. Every response — and every webhook — uses the canonical names.

Push a single lead

Request body

Scope: leads:write  |  Status: 201 Created
Phone numbers are validated as Indian numbers. International numbers are rejected with a 422 validation error.
Privacy (PII-strict tenants). If your tenant is configured for strict PII handling, every response — the single-push response, every row of a bulk response, even an invalid row — echoes a masked phone (••••3210) instead of the number you sent. The plaintext number is never returned once ingested. This is not a bug in your integration; it’s the same masking GET/list endpoints apply for that tenant.Every lead response also carries phone_last4 — the last four digits, plaintext, for every tenant. On a strict tenant it is the only stable partial identifier available (phone is masked and, once the lead reaches a terminal status, dropped entirely), so key your reconciliation on salesforce_lead_id and display phone_last4.

Duplicate lead → 409

A single push checks the campaign for an existing lead matching this one by phone hash or by salesforce_lead_id — either match is enough. If one is found, the push is rejected outright rather than silently creating a second row:
409 Conflict
id is the existing Yotel lead’s id; salesforce_lead_id is its existing SF id (null if that lead has none). Neither the request nor the response echoes a phone number.
lead_id means two different things in this API — read id instead.In a request body, and in every bulk result row, lead_id is the CRM lead id (an alias for salesforce_lead_id). In this 409 body it has always been Yotel’s own lead id. A client that joins on lead_id across the single and bulk paths is joining two different entities.The 409 now also returns that value as id — the same spelling, with the same meaning, that bulk result rows use. Read id here and salesforce_lead_id for the CRM id. lead_id is retained for backwards compatibility and should be treated as deprecated in this response.
status is the existing lead’s status and phone_purged says whether its number has been dropped. A lead that reaches dnd has its stored number purged on the spot; one that reaches completed, failed, busy or no_answer keeps it for the tenant’s retention window (default 30 days) and is purged after that. The dedup key is kept either way, so a re-push of a completed or dnd lead matches and the detail names the status. That lead will not be dialed again; re-pushing it is a no-op, not a re-queue. A re-push of an exhausted lead (failed, busy, no_answer — its attempt budget ran out) is a request to try again: it returns 201 and inserts a fresh, freshly scrubbed row.
If you’re re-sending the exact same push after a timeout or a retry — not intentionally re-pushing an existing lead — that’s what Idempotency-Key is for (see Idempotency): it returns your original 201 response instead of a 409, because Yotel recognizes the retry before dedup logic ever runs. Reach for Idempotency-Key on retries; expect (and handle) 409 when the lead genuinely already exists.

Bulk push leads

Push up to 500 leads in a single request. Invalid or duplicate leads are counted in the response but do not fail the request.
Bulk pushes are the one place we’d most recommend the Idempotency-Key header above — see Idempotency. A timed-out 500-lead batch is expensive to diagnose by hand; a retried request with the same key just returns the original result instead of re-processing.

Response

Scope: leads:write  |  Status: 200 OK
Privacy. A results row with status: "invalid" is always masked (••••2345, or null if the input had no recognizable digits at all) — on every tenant, not only PII-strict ones. We never echo a raw number back for a row that failed validation. On a PII-strict tenant, duplicate and added rows are masked too; on a standard tenant those two carry the plaintext number, same as GET responses do for that tenant.

DND scrubbing

Every lead is automatically checked against the TRAI DNC registry at ingestion. Leads flagged as DND get dnd_checked: true and dnd_clean: false — they will not be dialed but remain visible in the campaign for audit. This is a regulatory requirement and cannot be disabled.

Errors