Zinevu
API reference

Leads

The central record: the thing that arrives from a form, an ad or somebody's hand, and later grows an offer.

Leads and offers are the same row

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

leads:read

Every lead in the account, newest id last, cursor-paginated.

Parameters
status
string
Exact match — requested, offer, signed, …
source
string
Where the lead came from, exact match.
updated_since
ISO 8601
Only records changed at or after this instant.
limit
integer, 1–100
Defaults to 25.
cursor
string
From meta.next_cursor.
Request
curl "https://api.zinevu.com/api/public/v1/leads?status=requested&limit=25" \  -H "Authorization: Bearer $ZINEVU_API_KEY"
Response
{  "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}

leads:read

One lead, with the customer record embedded rather than referenced.

Response
{  "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

leads:write

Create a lead with its customer, the way a form would.

Parameters
namerequired
string, ≤255
A lead with no name is a row the dealer cannot act on.
email
string, ≤255
Validated as an address. Give at least an email or a phone.
phone
string, ≤255
Free text — it is what the dealer will dial.
street, house_number, postcode, city
string, ≤255
Stored on the customer's address.
country
ISO 3166-1 alpha-2
Defaults to the account's own country.
language
two letters
The customer's language. Defaults to nl.
source
string, ≤255
Your label for where it came from. Shown to the dealer.
note
string, ≤4000
Free text. Some senders paste the whole enquiry here.
answers
object, ≤100 entries
Question/answer pairs, kept verbatim.
Request
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 }  }'
Response
// -> 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" }}
What creating a lead does not do

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#

StatusMeans
requestedArrived. Nobody has quoted it yet.
offerAn offer exists on the record.
signedThe customer signed.
rejectedThe customer declined.
Accounts can carry further statuses of their own. Treat the field as an open enum.