A lead is an enquiry that has not yet been promoted to a full application. Leads are the only V1 resource with partial write support: you can POST to create them and PUT to update them. DELETE is wired in routes/api.php but the controller always returns 403 Forbidden.
Attributes
The shape returned by App\Http\Resources\V1\LeadResource::toArray():
| Attribute | Type | Description |
|---|---|---|
ID |
string (UUID) | Stable public identifier. |
EnterpriseID |
string (UUID) | UUID of the owning enterprise — derived via Team::find($team_id)->uuid. |
Title |
string | Lead title / one-line summary. |
Description |
string | null | Longer free-text description of the enquiry. |
PersonName |
string | null | Display name of the contact person. |
OrganisationName |
string | null | Display name of the contact organisation. |
CreatedAt |
string (ISO 8601) | Record creation timestamp. |
UpdatedAt |
string (ISO 8601) | Record updated timestamp. |
List leads
GET /api/v1/leads
Returns a paginated list of leads belonging to the enterprise identified by EnterpriseID. Page size is fixed at 100.
Request headers
| Header | Required | Description |
|---|---|---|
Authorization |
Yes | Bearer {token}. |
Accept |
Yes | application/json. |
EnterpriseID |
Yes | UUID of the enterprise. |
Responses
200— paginatedLeadsResourcecollection.403 Forbidden— caller is not a member of the enterprise.
Create a lead
POST /api/v1/leads
Creates a lead inside the enterprise identified by EnterpriseID. Validation is performed inline in LeadController::store() via Validator::make() — there is no Form Request class. V1 does not normalise body keys, so the validator accepts each pair of casings explicitly.
Body parameters
The minimum required fields, as enforced by the inline validator:
| Field | Type | Rules | Description |
|---|---|---|---|
Title or title |
string | required (one of the pair), max:255 | Lead title. Either casing is accepted via required_without. |
PersonName or person |
string | required (one of the pair), max:255 | Contact person display name (or identifier). Either casing is accepted via required_without. |
team |
mixed | required (auto-resolved) | Team id. Set automatically from the EnterpriseID header before validation runs — you do not need to send it. |
Any additional fields in the body are forwarded to LeadService::create() and stored on the new lead. Common extras used by the FinDesk client include: Description, OrganisationName, organisation, organisation_id, person_id, abn, has_abn, description, user_assigned_id, use, asset_description, purchase_price, deposit, trade_in, finance_amount, finance_term, residual, funds_required_within, realestate_owner, finance_last_3_years, applied_already, broker_id, phone, phone_type, email, email_type, source.
Responses
201 Created—LeadResourceenvelope ({ "data": { ... } }).400 Bad Request—{ "errors": { ... } }when validation fails.403 Forbidden— when the resolved team is missing or the caller does not belong to it.
Retrieve a lead
GET /api/v1/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/v1/leads/{lead:uuid}
Body parameters
update() runs the same inline validator as store() above: Title/title and PersonName/person remain required even on update, and team is auto-resolved from the EnterpriseID header. Partial updates that omit those required fields will fail validation with 400.
Responses
200— JSON body returned directly byLeadService::update()(not wrapped in a resource).400 Bad Request— validation errors.403 Forbidden— caller is not a member of the enterprise.
Delete a lead
DELETE /api/v1/leads/{lead:uuid}
Always returns 403 Forbidden. The route exists for parity, but the controller short-circuits before dispatching to a service.