Create a lead
POST /v1/leads — one call creates the customer, contact and lead, idempotently.
POST Create a lead
/v1/leadsCreates the customer, contact and lead in one call. The lead lands in your default lead workflow at its first stage, with the CRM's usual on-creation automations (stage actions, team assignment, notifications). If a customer with the same email and phone already exists, the lead is attached to them rather than creating a duplicate; otherwise a new customer and contact are created.
The call is idempotent on reference: the same reference returns the same lead with
created: false, so retries are safe.
Requirements
Three rules a single field cannot express. A body that breaks one is a 422 naming the field.
referenceis required.- A name:
firstNameand/orlastName, orcompanyName. - A way to contact them: at least one of
email,phoneNumber,mobile.
Everything else is optional. Send what you have. GET /v1/leads/fields
is the authoritative list, generated from the validator, with the valid values for every option
field.
referencestring · max 200RequiredYour own id for this submission, unique per submission, such as your form's row id. The same reference returns the same lead.
sourcestring · max 100A label for where the lead came from. Stored on the lead and filterable. Idempotency is per
reference within a source.
public-apitestbooleanMarks the lead as test data, excluded from reporting and from lists unless asked for.
falsefirstNamestring · max 100One of requiredlastNamestring · max 100One of requiredcompanyNamestring · max 250One of requiredtitleoptionAn option's id or name, from the CRM's title list.
customerTypeoptionAn option's id or name.
emailstring · email · max 255One of requiredphoneNumberstring · max 50One of requiredNormalised: spaces, dashes and brackets are removed and +44 becomes 0.
mobilestring · max 50One of requiredNormalised as phoneNumber. 07… numbers are mobiles.
addressstring · max 250address2string · max 250address3string · max 250townstring · max 100countystring · max 100postcodestring · max 20Upper-cased.
countryoptionAn option's id or name.
what3Wordsstring · max 100marketingoptionA marketing source's id or name, from your organisation's list.
subSourceCampaignoption · depends on marketingA campaign's id or name. Sent alone, its source is filled in; sent with marketing, they
must agree. Campaign names repeat under every source, so a campaign sent by name is looked up
within the marketing you sent; alone it is usually ambiguous and you will be asked for its
id.
leadTypeoptionAn option's id or name, such as Windows.
mainInterestoptionsalesAreaoptionleadProductTypesoption[] · max 50Shares its list with mainInterest; that is how the CRM models it.
propertyTypeoptionpropertyCategoryoptionplanningRequiredoptionplanningTypeoptionpropertyOtherstring · max 250yearBuiltinteger · 1000 to 2200idstring · max 200Use reference.
namestring · max 200Use firstName and lastName.
phonestring · max 50Use phoneNumber or mobile.
emailMarketingbooleanUse marketingEmail.
smsMarketingbooleanUse marketingSms.
Option fields take an option's id or its name: "leadType": "Repairs" and
"leadType": "3340ec93-…" are the same. See Conventions.
Unknown properties in the body are ignored; unknown query parameters on GET are not.
curl https://api.evacrm.co.uk/v1/leads \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{
"reference": "web-form-8812",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com",
"mobile": "07700 900123",
"address": "1 High Street",
"town": "Reading",
"postcode": "rg1 1aa",
"leadType": "Windows",
"marketing": "Website",
"marketingEmail": true,
"message": "Please call after 5pm",
"assignedTo": "tuan@example.com"
}'{
"created": true,
"reference": "web-form-8812",
"lead": { "uuid": "1e4e3f90-4384-42ce-90c3-540db5343964", "code": "L013898" },
"customer": { "uuid": "7b1d…", "code": "CUS007378" }
}Migrating from the old webhook
The webhooks.evacrm.co.uk intake accepted nine fields: id, name, email, phone,
postcode, message, smsMarketing, emailMarketing. All are still accepted here with the
same meaning, so an existing integration can switch the URL and add the key header without
other changes. GET /v1/leads/fields lists them as deprecated with replacedBy.
Two long-standing bugs are fixed in the process: real JSON booleans ("emailMarketing": true)
were recorded as false by the old intake, and +447… numbers were filed as landlines. Prefer
the explicit fields (firstName/lastName, mobile/phoneNumber, marketingEmail) for
anything new.