Skip to content

Creating and Updating Leads

This guide covers the public API endpoints for creating and updating leads, including accepted field formats and how to look up dealership-specific values such as lead status options.

For authentication setup, see Authentication. For updating lead outcomes (status) after creation, see Updating Lead Outcomes.

Action Method URL
Create lead POST https://dashboard.dealerstudio.com.au/api/v1/leads
Update lead PUT https://dashboard.dealerstudio.com.au/api/v1/leads/{id}

OpenAPI reference: Create Lead, Update Lead.

Every request must include:

{
"Authorization": "Bearer YOUR_API_KEY",
"Accept": "application/json",
"Content-Type": "application/json"
}

Your API key must include access to the target dealership. See the LMS overview for how to request a key and retrieve dealership identifiers.

{
"lead": {
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "0412345678",
"dealership_id": 123,
"category": "New Vehicle Enquiry",
"source": "Website",
"message": "Interested in a test drive"
}
}

201 Created:

{
"id": 456789,
"lead_cluster_id": 123456
}
  • id — the new lead record.
  • lead_cluster_id — the customer cluster this lead belongs to. Leads with the same email or phone at the same dealership are grouped into one cluster. Use this ID when updating lead status (see Lead status below).

If a field value is invalid, the API returns 422 Unprocessable Content with a JSON object describing the problem. Field names map to arrays of error messages.

Unknown location_id:

{
"location_id": ["is invalid: no location found with this id"]
}

location_id that belongs to a different dealership:

{
"location_id": ["must belong to dealership"]
}

Unknown page_id:

{
"page_id": ["is invalid: no page found with this id"]
}

Use GET /api/v1/dealerships/{dealership_slug}/locations to look up valid location IDs for a dealership.

Field Type Description
email string Customer email address
phone string Customer phone number
dealership_id integer Dealership ID, or use dealership_slug instead
category string Lead category — must be an exact match from the accepted values
source string Lead source — must be an exact match from the accepted values

Send a PUT request to /api/v1/leads/{id} with the same { "lead": { ... } } wrapper.

Every create and update request must include a dealership identifier — dealership_id, dealership_slug, or dealer_code — even when you are only changing other fields (for example message). Other lead fields can be omitted; only the dealership identifier and the fields you want to change need to be sent.

If the dealership identifier is missing, the API returns 422 Unprocessable Content:

{
"message": "dealership_id is required. Include dealership_id, dealership_slug, or dealer_code in the lead payload."
}
{
"lead": {
"dealership_id": 123,
"message": "Updated enquiry notes"
}
}
  • Dealership identifier: Required on every request (see above).
  • Age limit: API key requests cannot update leads created more than 3 days ago. Older updates return 200 OK with { "message": "You cannot edit this lead" }.
  • Payments: If the lead already has a payment, sending payment_attributes returns { "message": "Payment already exists" }.

These fields map directly to the lead record.

Field Type Required Description
name string No Customer full name
last_name string No Customer last name
email string Yes (create) Customer email
phone string Yes (create) Customer phone
message string No Free-text enquiry message
dealership_id integer Yes (create and update) Dealership ID
dealership_slug string Yes (create and update) Alternative to dealership_id
category string Yes (create) See Lead categories and sources
source string Yes (create) See Lead categories and sources
subsource string No More specific source attribution. See Subsource
marketing_source string No See Lead categories and sources
subcategory string No Form or funnel label; must match an allowed subcategory if provided
location_id integer No Dealership location ID
website_id integer No Website ID
website_slug string No Alternative to website_id
page_id integer No Page the lead was submitted from
car_id integer No Vehicle ID in Dealer Studio
stocknum string No Matches an in-stock vehicle by stock number when car_id is not supplied
provider string No Lead supplier name (e.g. Carsales)
provider_id string No External reference from the supplier
tags string[] No Tags applied to the lead and its cluster
golden boolean No Mark the cluster as high priority
team_member_id integer No Assign to a dealership user (by ID)
user_email string No Assign to a dealership user (by email)
send_customer_email boolean No Whether to send the customer confirmation email
disable_strict_validation boolean No When true, skips strict email and phone validation
skip_website_location_validation boolean No When true, skips validation that website_id and location_id belong to the lead’s dealership
linked_query_params object No Click IDs and UTM parameters from the customer’s landing page — see Marketing attribution
visited_pages string[] No Paths the customer visited before submitting (may include query strings)
user_agent string No Browser user-agent string from the submission
address_attributes object No Customer address — saved on the contact, not the lead (see below)

Provide one of dealership_id, dealership_slug, or dealer_code on every create and update request.

These fields are not columns on the lead itself. They are stored on the contact record linked to the lead.

Field Type Format Maps to
first_name string — contact.first_name
last_name string — contact.last_name (also stored on lead.last_name)
dob / date_of_birth / license_dob string DD/MM/YYYY or YYYY-MM-DD contact.date_of_birth (not stored in fields)
drivers_license / drivers_license_number / driver_licence_number / license_number string — contact.drivers_license_number (not stored in fields)
drivers_license_state / license_state string — contact.drivers_license_state (not stored in fields)
drivers_license_card_number / license_card_number string — contact.drivers_license_card_number (not stored in fields)
drivers_license_expiry / license_expiry string date contact.drivers_license_expiry (not stored in fields)
opt_in boolean — Lead column; also sets contact.opt_in_to_marketing when true
marketing_opt_in boolean — Treated like opt_in when true (not stored in fields)
Flat address keys (street, street_number, suburb, city, state, postcode, …) string — Promoted onto contact.address / contact.postcode when possible (not stored in fields). state alone (e.g. vehicle rego state) is kept in fields; it is only treated as address data when sent with other address keys. Prefer address_attributes for customer addresses
business_name string — contact.business_name (via fields)
abn string — contact.abn (via fields)
sms_verified boolean — contact.sms_verified

Send date of birth as dob or date_of_birth on the lead payload (top-level or inside fields):

{
"lead": {
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "0412345678",
"dealership_id": 123,
"category": "New Vehicle Enquiry",
"source": "Website",
"dob": "01/01/1980"
}
}

Accepted formats:

  • DD/MM/YYYY — e.g. 01/01/1980 (recommended for Australian integrations)
  • YYYY-MM-DD — e.g. 1980-01-01 (ISO 8601 date)

Both formats are parsed when the contact is created or updated. Invalid dates are ignored silently.

You can also send dob or date_of_birth inside the fields object, or as fields["Date Of Birth"]. These values are written to the contact and are not retained in lead.fields.

Send the licence number as drivers_license, drivers_license_number, or driver_licence_number (top-level or inside fields). It is stored on contact.drivers_license_number and is not retained in lead.fields.

{
"lead": {
"fields": {
"date_of_birth": "25/08/1995",
"drivers_license": "5331111",
"budget": "$50,000"
}
}
}
{
"lead": {
"address_attributes": {
"street": "123 Example Street",
"city": "Melbourne",
"state": "VIC",
"state_long": "Victoria",
"postcode": 3000,
"country": "Australia"
}
}
}

The address is geocoded and saved on the contact. It is not stored on the lead record.

Any parameter that is not a recognised lead column is automatically moved into the lead’s fields JSON object. Keys are normalised to snake_case (e.g. firstName becomes first_name). Contact PII such as first_name, date of birth, driver’s licence details, flat address keys, marketing_opt_in, and nested address_attributes are stored on the contact instead and are not retained in fields (see Contact fields).

You can send custom data either at the top level or explicitly in fields:

{
"lead": {
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "0412345678",
"dealership_id": 123,
"category": "New Vehicle Enquiry",
"source": "Website",
"preferred_contact_time": "Morning",
"fields": {
"campaign_id": "summer-2026",
"referral_code": "partner-xyz"
}
}
}

Both preferred_contact_time and the explicit fields entries are stored under fields on the lead.

For marketing attribution (Google click IDs, Facebook click IDs, UTM tags), use linked_query_params on the lead payload — not fields. See Marketing attribution below.

For document request leads, include document_type in fields (car_analysis, ppsr, or equifax). This applies when category is Document Request, or when category is New Vehicle Enquiry or Used Vehicle Enquiry and subcategory is Document Request.

Values must match exactly (case and spacing). See Lead categories and sources for the full lists of category, source, and marketing_source. The same enums appear in the OpenAPI schema on Create Lead.

Ford, Hyundai, Toyota, Jeep and GWM leads use Manufacturer as the source and identify the manufacturer through subsource:

{
"lead": {
"source": "Manufacturer",
"subsource": "Ford"
}
}

Accepted manufacturer subsources are Ford, Hyundai, Toyota, Jeep and GWM. Omit subsource when the manufacturer is not known.

Inbound phone-call leads always include subsource phone_call. The source is usually Phone Call, but a tracking number may override it (for example Website) while keeping phone_call as the channel marker:

{
"lead": {
"source": "Phone Call",
"subsource": "phone_call"
}
}

A subsource is rejected when it does not belong to the supplied source, except phone_call, which is accepted under any source.

On update, sending source on its own clears a stored subsource that does not belong to the new source. To move a lead between manufacturers, send source and subsource together.

You can set marketing_source explicitly, but in most integrations you should omit it and let Dealer Studio derive it from linked_query_params (see below).

Marketing attribution (click IDs and UTM parameters)

Section titled “Marketing attribution (click IDs and UTM parameters)”

When a customer lands on your site or app from a tracked campaign, capture the query parameters from the page URL (for example gclid, fbclid, utm_source) and send them in the lead create payload.

Important: Attribution parameters must be sent in the JSON request body, nested under lead.linked_query_params. Appending them to the API URL (for example POST /api/v1/leads?gclid=...) has no effect.

Send click IDs and UTM parameters as a key/value object on the lead:

{
"lead": {
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "0412345678",
"dealership_id": 123,
"category": "New Vehicle Enquiry",
"source": "Website",
"linked_query_params": {
"gclid": "EAIaIQobChMI...",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "dealer_sem"
},
"visited_pages": ["/new-cars/toyota-camry?gclid=EAIaIQobChMI..."],
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
}
}

Common keys include:

Key Description
gclid Google Ads click ID
gbraid, wbraid Google Ads enhanced conversions click IDs
gad_campaignid Google Ads campaign ID
fbclid Meta (Facebook/Instagram) click ID
utm_source Campaign source (e.g. google, facebook, email)
utm_medium Campaign medium (e.g. cpc, email)
utm_campaign Campaign name
utm_content, utm_term Optional UTM dimensions

Any additional query parameter keys from the landing page may also be included; they are stored on the lead for reporting and exports.

When linked_query_params is present, Dealer Studio sets marketing_source and utm_campaign on the lead from those values. You do not need to send marketing_source unless you want to override the derived value.

Parameters present marketing_source set to
gclid, gbraid, wbraid, or gad_campaignid Adwords
fbclid, or utm_source of facebook / fb Facebook
utm_source of ig Instagram
utm_source of msg Messenger
utm_source of an Audience Network
utm_source of tiktok TikTok
utm_source of youtube YouTube
utm_source of chatgpt or chatgpt.com ChatGPT
utm_source of qr_code QR Code
utm_source of gmb or googlemaps GMB
utm_source of email or edm, or utm_medium of email or edm Email
utm_source of sms SMS
utm_source of carsales Carsales
utm_source of linkedin Linkedin
utm_source of crm CRM

utm_source values are matched case insensitively, so ChatGPT and chatgpt both resolve to ChatGPT.

utm_campaign is taken from the first value when the parameter is sent as an array.

If you do not send linked_query_params, Dealer Studio can parse UTM and click-ID parameters from the query string of url in fields (the full page URL where the customer submitted the form):

{
"lead": {
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "0412345678",
"dealership_id": 123,
"category": "New Vehicle Enquiry",
"source": "Website",
"url": "https://dealer.example.com/enquiry?utm_source=google&gclid=abc123&utm_campaign=dealer_sem"
}
}

The url key is stored in fields automatically when it is not a recognised lead column. Prefer linked_query_params when you have discrete values — it is explicit, and takes precedence when both are sent.

  1. On page load, read query parameters from the customer’s browser URL (for example via window.location.search).
  2. Persist them in session storage or your form state until the customer submits.
  3. Include them in linked_query_params on POST /api/v1/leads.

Lead status is not set on POST /api/v1/leads or PUT /api/v1/leads/{id}. When a lead is created, its cluster is assigned the dealership’s default new status automatically.

To read or update status, use the lead cluster endpoints instead.

Lead status options are dealership-specific. Each dealership (and pipeline) can have custom status names. Do not hard-code status IDs or names — fetch them first:

GET /api/v1/dealerships/{dealership_slug}/lead_status_options

OpenAPI reference: List lead status options.

Example response (abbreviated):

[
{
"id": 762,
"name": "new",
"status_type": "new",
"active": true,
"position": 1,
"pipeline": { "id": 45, "name": "Sales" }
},
{
"id": 763,
"name": "contacted",
"status_type": "working",
"active": true,
"position": 2,
"pipeline": { "id": 45, "name": "Sales" }
}
]
Response field Description
id Use this as lead_status_option_id when updating a cluster
name Human-readable status name (also accepted as legacy lead_state)
status_type Internal category: new, working, converted, delivered, lost, or invalid
pipeline Which pipeline this status belongs to

Default status names for most dealerships are: new, contacted, converted, delivered, lost, and spam. Dealers can rename these or add custom statuses (e.g. Technigo Working).

Use the lead_cluster_id returned from lead create:

PUT /api/v1/dealerships/{dealership_slug}/lead_clusters/{lead_cluster_id}

Preferred — pass the ID from the lookup endpoint:

{
"lead_cluster": {
"lead_status_option_id": 762
}
}

Legacy — pass the status name as lead_state (must match a status name for that dealership’s pipeline):

{
"lead_cluster": {
"lead_state": "contacted"
}
}

See Updating Lead Outcomes for full details.

When a lead is created, Dealer Studio automatically groups it into a lead cluster based on matching customer email or phone at the same dealership. A returning customer with the same contact details is added to their existing open cluster rather than creating a duplicate contact.

The create response includes both id (lead) and lead_cluster_id (cluster). Store lead_cluster_id if you need to update status or receive cluster-level webhooks later.

Purpose Endpoint
Dealership locations and users GET /api/v1/apikeys/apikey_details.json
Lead status options GET /api/v1/dealerships/{slug}/lead_status_options
Update lead status PUT /api/v1/dealerships/{slug}/lead_clusters/{id}
Lead events (calls, SMS, notes) POST /api/v1/lead_events

See the LMS overview for the full integration workflow.