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
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.
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.
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.Response
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 getdnd_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.

