Overview
The Lead Post Webhook API accepts one JSON lead per request. TECOBI uses the supplied contact data to create a lead or link the request to an existing lead, then applies supported metadata, assignment, appointment, and comments fields.
Before you begin: Request an active client API key from your TECOBI representative. Keep the key server-side and never expose it in browser JavaScript or a public repository.
Bulk arrays are not supported. Send each lead as a separate request.
Endpoint
POST /api/v4/webhooks/lead-post/
Content-Type: application/json
x-tecobi-api-key: <client-api-key>
Authentication
Include the active client’s API key in the x-tecobi-api-key request header.
| Header | Required | Accepted value | Notes |
|---|---|---|---|
x-tecobi-api-key | Yes | Active TECOBI client API key | Missing or invalid keys return 400 Bad Request. |
Payload requirements
The request body must be a JSON object. At least one of these contact values must be present for TECOBI to create or link a CRM lead:
phone_numberphonecustomData.phone_numberemailcustomData.email
If no phone or email is supplied, the endpoint can still return 201 Created, but no CRM lead is created.
Unknown fields are retained in the raw webhook payload, but they do not affect lead creation unless they are listed in this reference.
Request examples
Minimal request
{
"first_name": "Jane",
"last_name": "Customer",
"phone_number": "15551234567",
"email": "jane@example.com",
"classification": "Sales"
}
Complete request
{
"lead_id": "abc-123",
"service": 5579,
"language_code": "en",
"classification": "Sales",
"first_name": "Jane",
"last_name": "Customer",
"phone_number": "15551234567",
"email": "jane@example.com",
"company": "Acme Co",
"address_1": "123 Main St",
"address_2": "Suite 4",
"city": "Denver",
"state": "Colorado",
"zip_code": "80202",
"assigned_to": "salesperson@exampledealer.com",
"sales_manager_email": "manager@exampledealer.com",
"appointment_time": "2026-08-12T15:00:00-06:00",
"appointment_notes": "Wants to test drive",
"appointment_location": "Showroom",
"comments": {
"Vehicle": "F-150",
"Budget": "$45k"
}
}
cURL request
curl --request POST \
--url 'https://<tecobi-api-origin>/api/v4/webhooks/lead-post/' \
--header 'Content-Type: application/json' \
--header 'x-tecobi-api-key: <client-api-key>' \
--data '{
"first_name": "Jane",
"last_name": "Customer",
"phone_number": "15551234567",
"email": "jane@example.com",
"classification": "Sales"
}'
Use the API origin supplied with your TECOBI client credentials.
Field reference
Lead identity
| Field | Type | Required | Accepted values | Behavior |
|---|---|---|---|---|
lead_id | String or number | No | Any external identifier | Stored as the external lead ID. |
contact_id | String or number | No | Any external identifier | Fallback external lead ID when lead_id is absent. |
first_name | String | No | Any non-empty string | Saved as the first name. Defaults to Unknown. |
last_name | String | No | Any non-empty string | Saved as the last name. Defaults to Unknown. |
customData.first_name | String | No | Any non-empty string | Fallback when top-level first_name is absent or Unknown. |
customData.last_name | String | No | Any non-empty string | Fallback when top-level last_name is absent or Unknown. |
Contact information
| Field | Type | Required | Accepted values | Behavior |
|---|---|---|---|---|
phone_number | String | Conditionally | US number with or without +1, spaces, dashes, dots, or parentheses | Preferred phone field. Normalized toward +1XXXXXXXXXX and matched within the client. |
phone | String | Conditionally | Same as phone_number | Fallback phone field. |
customData.phone_number | String | Conditionally | Same as phone_number | Nested fallback phone field. |
email | String | Conditionally | Email address | Preferred email field. Used for matching when no phone is available. |
customData.email | String | Conditionally | Email address | Nested fallback email field. |
At least one phone or email field is required for a lead to be created or linked.
Lead metadata
| Field | Type | Required | Accepted values | Behavior |
|---|---|---|---|---|
classification | String | No | Sales, Reseller, Service, Parts, Employment, Collections, Service Canceled | Defaults to Sales. Send a valid CRM classification. The database field is limited to 16 characters. |
service | Integer or integer string | No | Existing LeadProviderService.id | Defaults to 5579. Resolves provider, master provider, and service when the ID exists. |
customData.Service | Integer or integer string | No | Existing LeadProviderService.id | Fallback service ID. The capital S is required. |
language_code | String | No | Existing Language.code | Preferred language code. |
language | String | No | Existing Language.code | Fallback when language_code is absent. |
Assignment and roles
Each role accepts the email of an active user on the client. Send it at the top level or inside customData with the same key. An unmatched email does not fail the request; TECOBI creates an internal warning note.
| Field | Type | Required | Maps to |
|---|---|---|---|
assigned_to | String | No | Lead assignee |
secondary_rep_email | String | No | Secondary representative |
salesperson_2 | String | No | Secondary representative |
sales_manager_email | String | No | Sales manager |
bdc_rep_email | String | No | BDC representative |
finance_manager_email | String | No | Finance manager |
service_rep_email | String | No | Service representative |
parts_rep_email | String | No | Parts representative |
Address and company
| Field | Type | Required | Accepted values | Behavior |
|---|---|---|---|---|
company_name | String | No | Any string | Saved as the lead company name. |
company | String | No | Any string | Fallback company name. |
address | String | No | Any string | Primary street address. Can also provide a recognizable state fallback. |
address_1, address1, street | String | No | Any string | Primary street address fallbacks. |
address_2, address2 | String | No | Any string | Appended to the primary address. |
city | String | No | Any string | Saved as the lead city. |
state | String | No | Two-letter abbreviation or full US state name | Recognized full names are converted to abbreviations. |
postal_code, postalcode, zip, zip_code, zipcode | String | No | Any string | Saved as the lead postal code. |
Appointments
Appointment fields can be sent at the top level or inside customData with the same key.
| Field | Type | Required | Accepted values | Behavior |
|---|---|---|---|---|
appointment_time | String | No | Date/time string parseable by the API | Creates an appointment when valid. Naive times use the client’s timezone and are converted to UTC. Invalid values produce an internal warning, not a failed request. Duplicate active appointments at the same time are ignored. |
appointment_notes | String | No | Any string | Saved as appointment notes. |
appointment_location | String | No | Any string | Saved as the appointment location. |
Notes and comments
| Field | Type | Required | Accepted values | Behavior |
|---|---|---|---|---|
question_responses_lead_id | String | No | Pipe-delimited string | Split on ` |
comments | Any JSON value | No | String, object, array, or other JSON value | Creates an internal comments message and is included in the generated inbound message. |
message.body | String | No | Any string | Fallback comments source when comments is absent. |
customData.inquiry_details | String | No | Any string | Final comments fallback. |
Comments are normalized as follows:
- Object values become
key: valuelines. - Array values become one line per non-empty item.
- String values are retained as text.
- Pipe-and-colon strings such as
Color: Red|Trim: XLTbecome separatekey: valuelines.
Nested custom data
customData must be a JSON object. It provides fallback values for selected fields. Unknown nested keys remain in the raw payload but are ignored during lead creation.
Supported keys are phone_number, email, first_name, last_name, Service, all assignment and role keys, all appointment keys, and inquiry_details.
Lead processing behavior
Phone leads
TECOBI removes common punctuation and normalizes US phone values toward +1 format. Leads are matched by client and normalized number. Existing matching leads are reactivated to an active, fresh status when applicable.
Email-only leads
When no phone is supplied, TECOBI attempts to match an existing client lead by normalized email and compatible first and last name. If no match is found, it creates a new web lead.
New-lead defaults
| Lead field | Default behavior |
|---|---|
status_id | 1 |
lead_type | SMS with a phone number; otherwise Web |
lead_status | New |
twilio_number | Client default number |
script | Script assigned to the client default number |
classification | Request value, defaulting to Sales |
provider, master_provider, service | Derived from the resolved LeadProviderService |
Responses
Success
HTTP/1.1 201 Created
Content-Type: application/json
{}
The success body is always an empty JSON object and does not include the created or matched lead ID.
Missing API key
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"message": "x-tecobi-api-key header is required."
}
Invalid API key
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"message": "x-tecobi-api-key is not valid."
}
Implementation notes
- A valid request can return
201 Createdwithout creating a CRM lead when no phone or email is supplied. - Unknown fields are stored in the raw webhook payload but ignored by lead creation.
- Invalid role emails and invalid appointment times create internal warnings instead of failing the request.
- Lead creation is attempted synchronously during the request.
- Send exactly one lead per request.