Skip to content

Developers

Creating leads with the API

The full reference for POST /api/v1/leads, including the Idempotency-Key header, the request body and every outcome it can return

3 min readUpdated 26 September 2026

POST /api/v1/leads records an inbound lead. It runs the same intake path as every other source in ClientTurn: deduplication against existing leads, a suppression check, a record of permission, and attribution for the enquiry.

Requirements

  • An API key with the leads:write scope, belonging to someone with a member role or above.
  • An Idempotency-Key header: 8 to 200 printable characters, no spaces, unique per enquiry.
  • A JSON body.

Example

POST /api/v1/leads
Authorization: Bearer ct_live_…
Idempotency-Key: webflow-contact-sub_881
Content-Type: application/json
{
  "first_name": "Jo",
  "last_name": "Bloggs",
  "email": "jo@acme.co.uk",
  "phone": "07700 900123",
  "company_name": "Acme Studio Ltd",
  "relationship": "THEY_CONTACTED_US",
  "source": {
    "type": "WEB_FORM",
    "provider": "webflow",
    "record_id": "sub_881",
    "form_name": "Contact us",
    "utm_source": "google",
    "submitted_at": "2026-09-25T10:04:00Z"
  },
  "answers": { "Budget": "£5k–£10k" },
  "consent": { "marketing": true, "whatsapp": false, "evidence": "Ticked box v3 on /contact" }
}

Body fields

FieldRequiredNotes
relationshipYesOne of THEY_CONTACTED_US, EXISTING_CUSTOMER, REFERRAL, REQUESTED_INFORMATION, EXPLICIT_MARKETING_CONSENT, EXISTING_BUSINESS_RELATIONSHIP. A contact you merely found is a prospect, not a lead, and is not accepted here
email, phoneAt least oneUK numbers may be written in national format; they are normalised
first_name, last_name, company_name, role_title, postcodeNo
sourceNotype is WEB_FORM, API (default), CRM or CONNECTOR. provider is a lower-case name for the sending system (default api). Optional: record_id, form_id, form_name, campaign_id, campaign_name, utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid, fbclid, referrer, landing_url, submitted_at
answersNoQuestion-and-answer pairs from your form
consentNo, except for a referralmarketing and whatsapp (true or false) and free-text evidence. WhatsApp is only treated as allowed when whatsapp is true. With relationship REFERRAL, evidence is required: who referred them and when, in at least 20 characters
service_idNoThe ID of one of your services

Send submitted_at whenever you have it: speed-to-lead is measured from the time the person submitted, not from when ClientTurn received the request.

The response

Every successful call returns the outcome, never a bare "success":

{
  "data": {
    "outcome": "CREATED",
    "lead_id": "…",
    "touch_id": "…",
    "matched_by": null,
    "reasons": []
  }
}
outcomeHTTPMeaning
CREATED201A new lead was created
MERGED200The same person already existed (same email, or same phone with no conflicting email). Blank fields were filled, nothing was overwritten, and this enquiry was recorded as a new touch. matched_by says which rule matched
DUPLICATE200This Idempotency-Key, or this source.record_id, was already received. Nothing new was created. A repeated key also returns original_outcome
REVIEW200Recorded, but the phone number belongs to another lead with a different email. The two are not merged; a person decides
INVALID422No usable email or phone. Nothing was stored
REJECTED409The contact is on your suppression list. Nothing was stored: not the lead, not a touch, and not the idempotency key. reasons includes suppressed_refused

A suppressed contact is refused rather than recorded, because the API is creating a record and "nothing stored" is the honest answer. (Leads that arrive from ad forms are still recorded when suppressed, so you can see the enquiry, and are never contacted.)

If you reuse an Idempotency-Key with a different body, the first outcome is still returned and reasons includes idempotency_key_reused_with_different_body.

Follow-up is never started by the API

A lead created over the API is recorded, qualified and counted against your plan, but automated follow-up is not started. A person chooses to message it, or selects it in Leads and chooses Actions → Start follow-up. The API has nobody present to confirm an outbound action, so it never takes one.

Errors

A missing or malformed Idempotency-Key or body returns 400 invalid_request. So does a REFERRAL whose consent.evidence is shorter than 20 characters: nothing is stored, and the message says what to send. For the other error codes, see API overview and authentication.

Still stuck?

Customers can raise a ticket from the help button inside the app. Not a customer yet? Talk to us.

Contact us