Integrations & API
What it is
Two ways for Threadline and your other software to work together:
- Webhooks. Threadline tells another tool when something happens. See Webhooks for the plain-language explanation.
- The REST API. Another tool asks Threadline to do something, such as add a contact or send a message.
This page is the technical reference for both. Parts of it are written for a developer or for someone comfortable with tools like n8n and Zapier.
The problem it solves
Your customer data should not have to be typed twice. A website form, an online shop, a CRM and Threadline each hold part of the picture. Connecting them means:
- a customer who fills in a form on your website is added to Threadline and gets a WhatsApp message, with nobody doing anything;
- an order placed in your shop sends a "your order has shipped" message;
- every lead from Threadline lands in your spreadsheet or CRM.
How it works
- For webhooks, you add an endpoint under Webhooks and choose its events. Threadline sends a message to that address each time one happens.
- For the API, you create an access token under Developer, API tokens in the sidebar. The token is a long password that another program uses to prove it may act for your workspace. You decide what each token is allowed to do.
Creating an API token
- Go to Developer, API tokens in the sidebar. Your plan must include API access.
- Enter a name, so you remember what the token is for, for example "Zapier".
- Choose what it may do:
- Tick Full access for everything, including anything added later. Use it only for a program you fully trust.
- Or tick only the abilities that tool needs. See the list below.
- Optionally set an expiry date (a date in the future, up to five years away). After that date the token stops working and answers
401with a clear message. - Create it and copy the token straight away. It is shown only once.
If a token is lost or may have leaked, click Revoke and make a new one. A revoked token stops working at once. The token list shows each token's expiry and when it was last used.
Abilities (what a token may do)
| Ability | Lets the program… |
|---|---|
messages:send |
Send texts and templates. |
contacts:read / contacts:write |
Read contacts, segments and tags / create, change, delete and tag contacts. |
conversations:read / conversations:write |
Read conversations and messages / set a conversation's status or close it. |
campaigns:read / campaigns:write |
Read campaigns and their recipients / create, launch, pause and resume them. |
templates:read / templates:write |
Read WhatsApp templates / create drafts and submit them to Meta. |
automations:trigger |
List automations and start one for a contact. |
webhooks:write |
Manage webhook endpoints. |
ai:read / ai:write |
List assistants and knowledge bases / add knowledge and ask an assistant. |
deals:read / deals:write |
Read pipelines and deals / create and move deals. |
bookings:read / bookings:write |
Read bookable services, free times and bookings / create and cancel bookings. |
analytics:read |
Read the summary numbers. |
Treat a token like a password. Anyone who has it can read your contacts or send messages as your business, within what the token allows. Never put it in a public web page or share it in chat.
The rest of this page gives the exact formats.
1. Webhooks
Add an endpoint under Webhooks (see Webhooks). Every delivery is an HTTP POST of JSON, with the same envelope for every event:
{
"event": "message.received",
"data": { },
"timestamp": "2026-10-05T10:00:00+00:00"
}
Verifying the signature
Each delivery carries X-Threadline-Signature-256: sha256=<hex>. It is an HMAC-SHA256 of the raw request body, keyed with your endpoint's signing secret. Compute it yourself and compare in constant time; reject the request if it doesn't match.
$expected = 'sha256='.hash_hmac('sha256', $rawBody, $secret);
$valid = hash_equals($expected, $_SERVER['HTTP_X_THREADLINE_SIGNATURE_256'] ?? '');
Events and their data
message.received: a customer sent a message.
{
"message": { "id": 912, "conversation_id": 55, "text": "Hi, is this in stock?", "has_image": false, "received_at": "2026-10-05T10:00:00+00:00" },
"contact": { "id": 7, "name": "Ana Silva", "phone": "15551234567", "email": null, "channel_id": 2, "channel_type": "whatsapp", "opted_in": false }
}
contact.created: { "contact": { …same shape as above… } }
lead_form.submitted:
{
"lead_form": { "id": 3, "title": "Book a demo" },
"contact": { "id": 7, "name": "Ana Silva", "phone": "15551234567", "email": "ana@example.com", "channel_id": 2, "channel_type": "whatsapp", "opted_in": false },
"conversation_id": 55,
"answers": [ { "label": "Your name", "value": "Ana" }, { "label": "Email", "value": "ana@example.com" } ],
"completed_at": "2026-10-05T10:05:00+00:00"
}
conversation.escalated: { "conversation_id": 55, "reason": "keyword" }. The reason is one of fallback_phrase, human_requested, keyword or repeated_question.
conversation.closed: { "conversation_id": 55 }
answer.fallback: { "conversation_id": 55, "kb_id": 4, "question": "Do you ship to Nepal?" }
deal.created, deal.stage_changed, deal.won, deal.lost:
{
"deal": {
"id": 31, "title": "Website redesign", "value": 1500, "currency": "USD", "probability": 50,
"stage": "Proposal", "stage_kind": "open", "pipeline": "Sales Pipeline",
"contact_id": 7, "conversation_id": 55, "owner_user_id": 2,
"expected_close_on": "2026-11-01", "source_channel_type": "whatsapp",
"won_at": null, "lost_at": null, "lost_reason": null
},
"from_stage": "Qualified"
}
from_stage is present on the stage-change events only.
2. The REST API
Send your token on every request:
Authorization: Bearer kd_…
Accept: application/json
Everything is under /api/v1. A token belongs to one workspace and can only see that workspace's data. Each token is limited to 60 requests a minute; past that you get 429. A wrong, revoked or expired token gets 401; a token without the needed ability, or a workspace whose plan has no API access, gets 403.
The API reference page
You do not need this page to find every endpoint. Developer, API reference in the sidebar lists all 43 endpoints with their parameters, a ready-to-copy curl example and a sample answer, with a search box. It also has a quickstart, the error and rate-limit notes, how to check webhook signatures (with a Node example) and a download of the whole API as an OpenAPI 3 file you can load into Postman or code generators.
What the API covers
| Area | Examples |
|---|---|
| Account | GET /me, /channels, /analytics/summary |
| Contacts | list, create, show, update, delete, add and remove tags, /tags, /segments |
| Conversations | list, show, read messages, set status or close |
| Messages | POST /messages: send a text, or an approved template |
| Templates | list, show, create a draft, submit to Meta |
| Campaigns | list, show, recipients, create (and optionally launch), launch, pause, resume |
| Webhooks | list, create (the secret is shown once), update, delete (URLs must be public) |
| Assistants and knowledge | list, add text, a web page or questions and answers, ask an assistant |
| Automations | list, start one for a contact with extra data |
| Deals | list pipelines and deals, create in an open stage, move |
Not in the API: deleting a conversation, replying as a person, and changing who handles a conversation.
Lists are paginated: the response has data, links and meta.
# Add a contact who has agreed to hear from you, with a tag
curl -X POST https://your-site.com/api/v1/contacts \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"channel_id": 2, "phone": "+1 555 123 4567", "name": "Ana", "opted_in": true, "tags": ["website-lead"]}'
opted_in is your statement that the person agreed to marketing messages. The API can set it but never takes it away.
# Send a text (queued; answers 202)
curl -X POST https://your-site.com/api/v1/messages \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"contact_id": 7, "text": "Your order has shipped!"}'
# Start a conversation with an approved template (sent at once; answers 201)
curl -X POST https://your-site.com/api/v1/messages \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"channel_id": 2, "phone": "15551234567", "template_id": 12}'
The 24-hour rule applies: on WhatsApp, Instagram and Messenger a text only goes out within 24 hours of the person's last message, and otherwise answers 422 and tells you to use a template. A template needs an approved template and a contact who has opted in.
3. Recipe: new lead → Google Sheets, with n8n
- In n8n, add a Webhook node. Set the method to
POSTand copy its production URL. - In Threadline, Webhooks → Add endpoint, paste that URL and subscribe it to
lead_form.submitted. Copy the signing secret. - Add a lead form to your channel (see Lead Forms) and complete it once yourself so n8n receives a sample.
- In n8n, add a Google Sheets node after the webhook, set it to Append row, and map
{{ $json.body.data.contact.name }},{{ $json.body.data.contact.phone }}and{{ $json.body.data.answers[1].value }}to columns. - Optional: add a Code node between them to check the signature (section 1) before trusting the data.
- Activate the workflow. Every completed form now adds a row.
4. Recipe: send a WhatsApp message from a form, with Zapier
- In Threadline, make a token with Create contacts and Send messages, and find your WhatsApp channel's id and an approved template's id.
- In Zapier, set the trigger to your form tool's New submission.
- Add a Webhooks by Zapier action, event Custom Request, method
POST, URLhttps://your-site.com/api/v1/contacts, headerAuthorization: Bearer <token>, and a JSON body with the form's name and phone,"channel_id"and"opted_in": trueif the form asks for consent. - Add a second Custom Request to
/api/v1/messageswith{"channel_id": 2, "phone": "<the phone>", "template_id": 12}. - Test and publish the Zap.
5. Other ways in
- Automation webhook trigger. An automation can start when your system calls a private address. No API token is needed; the secret is in the address.
- Online stores send their own webhooks to Threadline. See Online Stores.
6. Meta lead ads
Lead ads from Facebook and Instagram can create contacts for you automatically. The full setup, including Meta's approval steps, is on its own page: Meta Lead Ads.
7. WhatsApp links
Short links and QR codes that open a chat with you and show which advert brought each customer. See WhatsApp Links.
Common questions
I get 401. The token is wrong or was revoked. Create a new one.
I get 403. The token works but is not allowed to do that. Create a token with the ability you need.
I get 429. You sent more than 60 requests in a minute with that token. Wait a moment and slow down.
I get 422 when sending a text. The 24-hour window has closed for that contact. Send an approved template instead.
I get 401 and the message mentions expiry. The token's expiry date has passed. Make a new one.
API access is missing from Settings. Your plan does not include API access. See Plans & Billing.