Skip to content

POST /v1/inbound/leads

Принять новый лид от партнёра.

Запрос

http
POST /v1/inbound/leads HTTP/1.1
Host: cartelcrm.com
Authorization: Bearer <api_key>
X-Signature: sha256=<HMAC-SHA256(body, hmac_secret)>
X-Timestamp: <unix seconds>
Idempotency-Key: <ваш-уникальный-id>
Content-Type: application/json

Body

Минимально-достаточный набор (если ваш партнёр не использует кастомный field_mapping):

ПолеТипОбяз.Описание
external_idstringнет*Ваш id лида. Если не передан — будет использован Idempotency-Key.
first_namestringнетИмя.
last_namestringнетФамилия.
full_namestringнетЕсли не передан — соберём из first_name + last_name.
emailstringнетEmail (хранится зашифрованно + хэш для поиска).
phonestringдаТелефон в международном формате с +. Шифруется + хэшируется.
countrystringнетСтрана. 2-буквенный ISO предпочтителен.
country_codestringнетЕсли не передан — выведем из country.
languagestringнетISO-код языка (en, ru, es...).
ipstringнетIP клиента. Если не передан — возьмём IP запроса.
user_agentstringнетUA клиента.
sourcestringнетИсточник трафика (facebook_ads, google, email, ...).
funnelstringнетКакая воронка лила.
sub_idstringнетВаш sub-id для пост-бэк трекинга.
click_idstringнетВаш click-id.
landing_urlstringнетURL посадки, где заполнялась форма.
metadataobjectнетЛюбые ваши дополнительные поля.

* Хотя external_id формально опционален, очень советуем передавать — иначе у вас не будет стабильного ключа для последующего GET /v1/inbound/leads/{externalId}/status.

Вложенный payload

Если вы шлёте в своём формате (profile.firstName, contact.phone, и т.д.) — это нормально. Менеджер настроит Field mapping под ваш payload, без изменений на вашей стороне.

Пример тела

json
{
  "external_id": "aff42-lead-001",
  "first_name": "Иван",
  "last_name": "Петров",
  "phone": "+380501234567",
  "email": "ivan@example.com",
  "country": "UA",
  "language": "ru",
  "source": "facebook_ads",
  "funnel": "crypto-v3",
  "sub_id": "sub-789",
  "click_id": "fb-click-abc",
  "landing_url": "https://landing.example/cr/v3?utm=fb"
}

Ответы

200 OK — лид принят

json
{
  "id": "le-12345",
  "status": "accepted",
  "reason": null,
  "duration_ms": 42
}
  • id — наш internal id, его удобно сохранить у себя для дебага.
  • duration_ms — сколько у нас занял весь intake (валидация → дедуп → сохранение → распределение).

После 200 — ждите callback lead.accepted, а потом — события смены статуса.

409 Conflict — duplicate

json
{
  "id": "le-12340",
  "status": "duplicate",
  "reason": "matched_lead:12340"
}

Найден лид в окне дедупликации (default 30 дней) с совпавшим phone или email. id — это id существующего лида (не нового). Никаких изменений в базе не произошло.

422 Unprocessable Entity — валидация / бизнес-правила

json
{
  "id": null,
  "status": "validation_error",
  "reason": "missing_required:phone"
}

или

json
{
  "id": null,
  "status": "rejected",
  "reason": "country_blocked:US"
}

См. Коды ошибок для полного списка reason.

200 OK с replay: true — идемпотентный повтор

json
{
  "id": "le-12345",
  "status": "accepted",
  "reason": null,
  "replay": true
}

Если вы повторили запрос с тем же Idempotency-Key (в окне 24 часов), мы вернули сохранённый результат без обработки. См. Idempotency.

401 Unauthorized / 403 Forbidden

См. Authentication и Коды ошибок.

429 Too Many Requests

json
{
  "error": "rate_limit_exceeded",
  "message": "Try again in 18 seconds"
}

Заголовок Retry-After содержит время до разблокировки. См. Rate limits.

Полный cURL-пример

bash
BODY='{"external_id":"aff42-lead-001","phone":"+380501234567","source":"facebook_ads","country":"UA"}'
TS=$(date +%s)
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$HMAC_SECRET" -hex | awk '{print $2}')

curl -X POST https://cartelcrm.com/api/v1/inbound/leads \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Signature: sha256=$SIG" \
  -H "X-Timestamp: $TS" \
  -H "Idempotency-Key: aff42-lead-001-r0" \
  -H "Content-Type: application/json" \
  -d "$BODY"

См. также: Примеры на Node/PHP/Python.

Закрытая партнёрская документация. Не для публичного распространения.