Connect your Tradello lead management to Zapier, Make or your own systems: add leads from your website, move them through your pipeline, log calls and tasks, and hear the moment a lead is won.
tdl_ and is shown once: Tradello keeps only a fingerprint of it. If it is lost, revoke it and make another.Authorization: Bearer tdl_…. Never put it in a web address or in a web page.Base address: https://www.tradello.co.uk/api/v1. Everything is JSON. Dates are ISO 8601 in UTC (2026-11-03T09:00:00Z). The machine-readable description is at /api/v1/openapi.json (OpenAPI 3.1).
What a key can never reach. Quote figures: they are locked on your devices with your company’s own key, so Tradello’s servers cannot read them and neither can the API. A key also sees only your account’s own lead management: the details Tradello publishes about a record stay on the record’s own screens, and a contact you linked from a published record is served without its email or numbers.
| Permission | Lets the key |
|---|---|
leads:read | Read leads, stages and team members |
leads:write | Add leads, move their stage and change their owner |
contacts:read | Read contacts |
contacts:write | Add and change contacts |
activities:write | Log notes, calls and emails on a lead |
tasks:write | Add tasks and mark them done |
webhooks:manage | Add and remove webhooks (for Zapier and Make triggers) |
| Request | Needs | Does |
|---|---|---|
GET /me | any | The key you are using and its permissions. Use it to test a connection. |
GET /leads | leads:read | Your leads, newest first. Filter with stage, owner, updated_since, created_since, archived. |
POST /leads | leads:write | Add a lead. |
GET /leads/{id} | leads:read | One lead. |
PATCH /leads/{id} | leads:write | Move it to another stage, change its owner or its details. |
GET /contacts | contacts:read | Your contacts, newest first. Filter with email, lead_id, updated_since. |
POST /contacts | contacts:write | Add a contact, optionally linked to a lead. |
GET /contacts/{id} | contacts:read | One contact. |
PATCH /contacts/{id} | contacts:write | Change a contact. |
POST /activities | activities:write | Log a note, a call or an email on a lead’s timeline. |
POST /tasks | tasks:write | Add a task. |
POST /tasks/{id}/complete | tasks:write | Mark a task done. |
GET /stages | leads:read | Your pipeline stages, in board order, with their keys. |
GET /members | leads:read | Your team: the emails a lead or task can be given to. |
GET /webhooks | webhooks:manage | Your webhooks. |
POST /webhooks | webhooks:manage | Add a webhook. Its signing secret is in this answer only. |
DELETE /webhooks/{id} | webhooks:manage | Remove a webhook. |
Pages. Lists return up to limit records (default 50, most 100), newest first, and a nextCursor. Pass it back as ?cursor= for the next page; it is null on the last one. To pick up only what changed, pass updated_since with the time of your last run.
{
"data": [ { "id": "…", "title": "Warehouse re-roof, Unit 4", "stage": { "key": "quoting", … } } ],
"page": { "limit": 20, "nextCursor": "eyJjIjoi…" }
}List leads at the Quoting stage
curl https://www.tradello.co.uk/api/v1/leads?stage=quoting&limit=20 \
-H "Authorization: Bearer $TRADELLO_KEY"Add a lead from your website
curl -X POST https://www.tradello.co.uk/api/v1/leads \
-H "Authorization: Bearer $TRADELLO_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Warehouse re-roof, Unit 4",
"companyName": "Northgate Logistics Ltd",
"postcode": "CH41 1AA",
"source": "website",
"owner": "sam@yourcompany.co.uk",
"estimatedValuePence": 4800000
}'Move a lead to another stage (keys come from GET /stages)
curl -X PATCH https://www.tradello.co.uk/api/v1/leads/LEAD_ID \
-H "Authorization: Bearer $TRADELLO_KEY" \
-H "Content-Type: application/json" \
-d '{ "stage": "quote_sent" }'Log a call
curl -X POST https://www.tradello.co.uk/api/v1/activities \
-H "Authorization: Bearer $TRADELLO_KEY" \
-H "Content-Type: application/json" \
-d '{ "leadId": "LEAD_ID", "type": "call", "outcome": "connected",
"notes": "Wants a site visit next week" }'Add a task
curl -X POST https://www.tradello.co.uk/api/v1/tasks \
-H "Authorization: Bearer $TRADELLO_KEY" \
-H "Content-Type: application/json" \
-d '{ "title": "Send revised drawings", "leadId": "LEAD_ID",
"dueAt": "2026-11-03T09:00:00Z" }'A webhook is an https:// address of yours that Tradello tells when something happens. Add one in Integrations (or with POST /webhooks), choose its events, and copy its signing secret — shown once, starting whsec_.
| Event | Sent when |
|---|---|
lead.created | A lead is added (by a person, quick add, the API or a form) |
lead.stage_changed | A lead moves to another stage |
lead.won | A lead moves to a Won stage |
lead.lost | A lead moves to a Lost stage |
contact.created | A contact is added |
task.created | A task is added |
enquiry.received | An enquiry arrives through your website form |
POST https://your-app.example/hooks/tradello
Tradello-Event: lead.won
Tradello-Delivery: 6f1c…
Tradello-Timestamp: 1761055200
Tradello-Signature: v1=5d41402abc4b2a76b9719d911017c592…
{
"id": "evt_0b7e…",
"type": "lead.won",
"createdAt": "2026-10-21T14:00:00.000Z",
"apiVersion": "2026-10-21",
"data": {
"lead": { "id": "…", "title": "Warehouse re-roof, Unit 4",
"stage": { "key": "won", "label": "Won", "kind": "won" }, … },
"previousStage": { "key": "negotiating", "label": "Negotiating", "kind": "open" }
}
}Check every delivery. Tradello-Signature is v1= and the HMAC-SHA256, in hex, of <Tradello-Timestamp>.<raw body>, keyed with your signing secret. Refuse a delivery whose signature does not match, or whose timestamp is more than 5 minutes from your clock, and remember the event ids you have handled so a repeat is ignored.
import crypto from 'node:crypto';
// rawBody: the request body exactly as received (a string, before JSON.parse)
function isFromTradello(rawBody, headers, secret) {
const ts = Number(headers['tradello-timestamp']);
// 1. Refuse anything older (or newer) than 5 minutes.
if (!Number.isInteger(ts) || Math.abs(Date.now() / 1000 - ts) > 300) return false;
// 2. Recompute the signature over "<timestamp>.<body>".
const expected = 'v1=' + crypto.createHmac('sha256', secret)
.update(ts + '.' + rawBody).digest('hex');
const got = String(headers['tradello-signature'] ?? '');
// 3. Compare in constant time.
return got.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}
// 4. Remember each event "id" you have handled and ignore repeats.GET /leads?updated_since= to catch up if you need certainty.lead.won, save. Press Send test.data lead title once a lead is won.https://www.tradello.co.uk/api/v1/leads, payload type JSON.title, companyName, postcode, source = website, mapped from the form.Authorization = Bearer tdl_… (a key with leads:write).https://www.tradello.co.uk/api/v1/leads, header Authorization: Bearer tdl_…, body type JSON.120 requests per minute per key. Every answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; over the limit you get 429 with Retry-After (seconds).
Errors have one shape. 400 the request was not valid (unknown fields are refused, not ignored) · 401 no valid key · 403 the key lacks the permission, or your plan no longer includes lead management · 404 no such record in your account (the same answer whether it never existed or belongs to someone else) · 409 it already exists · 429 slow down · 503 try again shortly.
HTTP/1.1 403 Forbidden
{ "error": { "code": "insufficient_scope",
"message": "This key does not have the leads:write permission. …" } }