curl --request POST \
--url https://app.thinnest.ai/api/v1/conversations/{id}/reply \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Yes — it left our warehouse this morning. Tracking: AB123456."
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({text: 'Yes — it left our warehouse this morning. Tracking: AB123456.'})
};
fetch('https://app.thinnest.ai/api/v1/conversations/{id}/reply', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/conversations/{id}/reply"
payload = { "text": "Yes — it left our warehouse this morning. Tracking: AB123456." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"ok": true
}Reply to Conversation
Your own agent platform answers a WhatsApp customer — the other half of the message.received webhook. Send exactly one of text, media, template or form; text, media and forms need the customer’s 24-hour window open, a template does not. Only works on a number with Connect External Agent/CRM turned on, and not while a teammate has taken the conversation over. Each message is charged like any WhatsApp message from that number. Needs a full key.
curl --request POST \
--url https://app.thinnest.ai/api/v1/conversations/{id}/reply \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Yes — it left our warehouse this morning. Tracking: AB123456."
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({text: 'Yes — it left our warehouse this morning. Tracking: AB123456.'})
};
fetch('https://app.thinnest.ai/api/v1/conversations/{id}/reply', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/conversations/{id}/reply"
payload = { "text": "Yes — it left our warehouse this morning. Tracking: AB123456." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"ok": true
}Authorizations
Your API key (ta_live_…) from Settings → API keys, sent as Authorization: Bearer <key>. Keep it on a server: it can message every customer you have. A key is full, build or read-only; a request its level does not allow is refused with 403.
Headers
Any unique string. A retry with the same key within 24 hours returns the first request's answer instead of acting twice.
255Developers only: the customer workspace this request acts in — its org_… id from POST /customers. Leave it out to act in your own workspace. Refused with 404 (Workspace not found.) when the id is unknown, is not one of your customers, or is not an org_… id; 410 when that customer was deleted (restore it with POST /customers/{id}/restore until it is erased); 403 when the key belongs to one customer workspace (it cannot act as another); 400 when your workspace is not a developer workspace. /customers/* and GET /customers/usage are your own workspace's and refuse the header with 400: call them without it.
"org_3fKq9TzQ1mN8vB2xR7cLpA"
Path Parameters
The conversation's id (conv_…) — the conversationId in the message.received delivery.
Body
- Text
- Media
- Template
- Form
Exactly one of text, media, template or form. Two in one call are refused, so a customer never gets two messages when you meant one.