A lead is an enquiry that has not yet been promoted to a full application. Leads are the only V2 resource with partial write support: you can POST to create them and PUT to update them. DELETE is wired but always returns 403 Forbidden.
Attributes
The shape returned by App\Http\Resources\V2\LeadResource::toArray():
| Attribute | Type | Description |
|---|---|---|
id |
string (UUID) | Stable public identifier. |
enterprise_id |
string (UUID) | null | UUID of the owning enterprise (team?->uuid). |
title |
string | Lead title / one-line summary. |
description |
string | null | Longer free-text description of the enquiry. |
person_name |
string | null | Display name of the contact person. |
organisation_name |
string | null | Display name of the contact organisation. |
created_at |
string (ISO 8601) | Record creation timestamp. |
updated_at |
string (ISO 8601) | Record updated timestamp. |
List leads
GET /api/v2/leads
Returns a paginated list of leads belonging to the enterprise identified by the X-Enterprise-Id header. Page size is fixed at 100.
Request headers
| Header | Required | Description |
|---|---|---|
Authorization |
Yes | Bearer {token}. |
Accept |
Yes | application/json. |
X-Enterprise-Id |
Yes | UUID of the enterprise. |
Responses
200— paginatedLeadsResourcecollection.403 Forbidden— caller is not a member of the enterprise.
Create a lead
POST /api/v2/leads
Creates a lead inside the enterprise identified by X-Enterprise-Id. The body is normalised by NormalizeApiInput before validation, so FirstName / firstName / first_name all reach the validator as first_name.
Body parameters
Validated by App\Http\Requests\Api\V2\StoreLeadRequest:
| Field | Type | Rules | Description |
|---|---|---|---|
title |
string | required, max:255 | Lead title. |
person |
string | required_without:person_name, nullable, max:255 | Contact person identifier or label. Either person or person_name is required. |
person_name |
string | required_without:person, nullable, max:255 | Contact person display name. |
person_id |
mixed | nullable | Internal person id when promoting an existing person record. |
organisation |
string | nullable, max:255 | Organisation identifier or label. |
organisation_name |
string | nullable, max:255 | Organisation display name. |
organisation_id |
mixed | nullable | Internal organisation id. |
has_abn |
mixed | nullable | Whether the organisation has an ABN. |
abn |
string | nullable | Australian Business Number. |
description |
string | nullable | Free-text description. |
user_assigned_id |
mixed | nullable | User id the lead should be assigned to. |
use |
string | nullable | Intended use of the asset (e.g. Business, Personal). |
asset_description |
string | nullable | Description of the asset being financed. |
purchase_price |
mixed | nullable | Purchase price of the asset. |
deposit |
mixed | nullable | Deposit amount. |
trade_in |
mixed | nullable | Trade-in value. |
finance_amount |
mixed | nullable | Amount to be financed. |
finance_term |
mixed | nullable | Finance term in months. |
residual |
mixed | nullable | Residual amount. |
funds_required_within |
string | nullable | Free-text urgency (e.g. 2 weeks). |
realestate_owner |
mixed | nullable | Whether the customer owns real estate. |
finance_last_3_years |
mixed | nullable | Whether the customer has financed in the last 3 years. |
applied_already |
mixed | nullable | Whether the customer has applied elsewhere. |
broker_id |
mixed | nullable | Broker id to attribute the lead to. |
phone |
string | nullable | Contact phone number. |
phone_type |
string | nullable | Phone type label (e.g. mobile, work). |
email |
string | nullable, email | Contact email. |
email_type |
string | nullable | Email type label (e.g. work, personal). |
source |
string | nullable | Lead source (e.g. Website enquiry form). |
team |
mixed | required | Team id. Auto-resolved from X-Enterprise-Id in prepareForValidation(); you do not need to send it. |
Responses
201 Created—LeadResourceenvelope ({ "data": { ... } }).400 Bad Request—{ "errors": { ... } }when validation fails.403 Forbidden—{ "message": "Forbidden" }when the resolved team is missing or the caller does not belong to it.
Retrieve a lead
GET /api/v2/leads/{lead:uuid}
Responses
200—LeadResourceenvelope.403 Forbidden— caller is not a member of the enterprise, or the lead'steam_iddoes not match.
Update a lead
PUT /api/v2/leads/{lead:uuid}
Body parameters
UpdateLeadRequest accepts the same fields as StoreLeadRequest above. title, team, and one of person / person_name remain required even on update — partial updates that omit them will fail validation with 400.
Responses
200— JSON body returned directly byLeadService::update().400 Bad Request— validation errors.403 Forbidden— caller is not a member of the enterprise or the lead does not belong to the resolved team.
Delete a lead
DELETE /api/v2/leads/{lead:uuid}
Always returns 403 Forbidden. The route exists for parity, but the controller short-circuits before dispatching to a service.
V2 differences — Every write endpoint on this resource passes through
App\Http\Middleware\NormalizeApiInput. Keys are recursivelyStr::snake()-converted, so mixed-case bodies (PersonName,personName,person_name) all validate against the snake-case rules above. If you send bothpersonNameandperson_namein the same request, whichever comes later wins — the snake-case sibling overwrites the camelCase one because both normalise to the same key.