Leads
The central record: the thing that arrives from a form, an ad or somebody's hand, and later grows an offer.
An offer is this record seen from the other end, once it has been quoted — not a separate object to join to. /offers is the same data with the line items and the offer timestamps in front.
GET/leads
scopeleads:readEvery lead in the account, newest id last, cursor-paginated.
requested, offer, signed, … meta.next_cursor.curl "https://api.zinevu.com/api/public/v1/leads?status=requested&limit=25" \ -H "Authorization: Bearer $ZINEVU_API_KEY"{ "data": [ { "id": 14868, "uuid": "0f2a…", "status": "requested", "type": "lead", "source": "form", "created_via": "quick_quote", "language": "nl", "currency": "eur", "total": 8420.5, "total_includes_vat": true, "sales_person": null, "campaign_id": null, "customer_id": 9931, "answers": { "breedte_cm": 400, "diepte_cm": 300, "dak": "polycarbonaat" }, "offer": { "number": null, "created_at": null, "sent_at": null, "signed_at": null, "rejected_at": null, "measurement_accepted_at": null }, "created_at": "2026-09-21T09:14:03+00:00", "updated_at": "2026-09-21T09:14:03+00:00" } ], "meta": { "message": "OK", "has_more": true, "next_cursor": "aWQ6MTQ4Njg", "limit": 25 }}GET/leads/{id}
scopeleads:readOne lead, with the customer record embedded rather than referenced.
{ "data": { "id": 14868, "status": "requested", "customer_id": 9931, "customer": { "id": 9931, "customer_no": "K-2026-0412", "name": "J. de Vries", "email": "[email protected]", "language": "nl", "address": { "street": "Dorpsstraat", "house_number": "12", "postcode": "3811 AB", "city": "Amersfoort", "country": "NL", "phone": "+31 6 1234 5678" } }, "answers": { … } }, "meta": { "message": "OK" }}The answers object#
answers is what the customer actually configured — the questions your funnel asked, with the values they picked. Keys are the dealer's own question keys, so they differ per account and per form; read it as a map, not as a schema. A lead created through the API carries whatever the sender passed, under its own envelope, and is never mixed into the configurator's key space.
POST/leads
scopeleads:writeCreate a lead with its customer, the way a form would.
email or a phone.curl -X POST https://api.zinevu.com/api/public/v1/leads \ -H "Authorization: Bearer $ZINEVU_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 4f3c…" \ -d '{ "name": "J. de Vries", "email": "[email protected]", "phone": "+31 6 1234 5678", "postcode": "3811 AB", "city": "Amersfoort", "source": "Marktplaats", "note": "Wants a 4x3 veranda, glass roof, asks about lead time.", "answers": { "breedte_cm": 400, "diepte_cm": 300 } }'// -> 201{ "data": { "id": 14903, "uuid": "7c11…", "status": "requested", "created_via": "api", "customer_id": 9974, "created_at": "2026-09-23T08:20:11+00:00" }, "meta": { "message": "Lead created" }}It never prices, never sends anything to the customer, and never updates an existing lead. A repeat request from the same person is deliberately a new lead in this product — the dealer needs to see that they asked three times — so retry with an Idempotency-Key rather than relying on an upsert that does not exist.
Quota#
A created lead spends the account's lead quota like any other. When it is spent the answer is 402 quota_reached — a limit, not a failure, and not something to retry.
Statuses#
| Status | Means |
|---|---|
requested | Arrived. Nobody has quoted it yet. |
offer | An offer exists on the record. |
signed | The customer signed. |
rejected | The customer declined. |
… | Accounts can carry further statuses of their own. Treat the field as an open enum. |