V2 · Core resources

Leads

Create, read, and update leads inside an enterprise pipeline.

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 — paginated LeadsResource collection.
  • 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 CreatedLeadResource envelope ({ "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

  • 200LeadResource envelope.
  • 403 Forbidden — caller is not a member of the enterprise, or the lead's team_id does 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 by LeadService::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 recursively Str::snake()-converted, so mixed-case bodies (PersonName, personName, person_name) all validate against the snake-case rules above. If you send both personName and person_name in the same request, whichever comes later wins — the snake-case sibling overwrites the camelCase one because both normalise to the same key.