Make a Text Hook
A Text Hook is an address any app can post to (Calendly, Typeform, Shopify, Stripe, Jotform, your own form) that turns the post into a text from your number.
/v1/hooks
A Text Hook is an address any app can post to (Calendly, Typeform, Shopify, Stripe, Jotform, your own form) that turns the post into a text from your number. mapping says which posted field is the person’s number and what to say, with {{body.…}} for posted fields.
Anyone with the address can send texts from your number, so keep it private. Start with test_mode on to check a real post without sending.
Needs a key with the messages:send scope.
Send an Idempotency-Key so a retry never acts twice.
Headers
Idempotency-KeystringAny string of up to 255 characters, new for each request. A retry with the same key gets the first answer back for 24 hours, with
Idempotent-Replayed: true.Up to 255 characters.
Request body
namestringrequiredUp to 80 characters.
presetstringStart from the usual fields of Calendly, Typeform, Shopify, Stripe or Jotform.
One of
calendly,typeform,shopify,stripe,jotform.mappingobjectShow its 5 fieldsHide its fields
tostringUp to 200 characters.
textstringUp to 2,000 characters.
first_namestringUp to 200 characters.
last_namestringUp to 200 characters.
tagsstringUp to 200 characters.
template_idstringA saved template to use instead of
text.Starts with
tpl_.sequence_idstring or nullA seq_ id.
Starts with
seq_.test_modebooleanDefault
false.
Example
/v1/hookscurl -X POST "https://usebluebot.com/api/v1/hooks" \
-H "Authorization: Bearer $BLUEBOT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0f6d8c2e-5b1a-4c7e-9d3f-2a8b6e1c4d70" \
-d '{
"name": "Calendly bookings",
"preset": "calendly",
"test_mode": true
}'Response
201: The Text Hook, with its address.
idstringrequiredA hook_ id.
Starts with
hook_.object"text_hook"requirednamestringrequiredurlstringrequiredThe address to post to. Anyone with it can send texts from your number, so keep it private.
enabledbooleanrequiredtest_modebooleanrequiredPosts are recorded and checked but no text is sent.
mappingobjectrequiredHow a post becomes a text. Each value is a template over the posted fields:
bodyfor the JSON or form,queryfor the address’s query string.Show its 5 fieldsHide its fields
tostring or nullrequiredWho to text, as a
{{body.…}}path into the posted fields.Up to 200 characters.
textstring or nullrequiredThe words, with
{{body.…}}fields. Leave it empty to usetemplate_id.Up to 2,000 characters.
first_namestring or nullrequiredSaved on the contact when it has no first name yet.
Up to 200 characters.
last_namestring or nullrequiredUp to 200 characters.
tagsstring or nullrequiredTags to add, separated by commas. May use
{{body.…}}fields.Up to 200 characters.
template_idstring or nullrequiredsequence_idstring or nullrequiredA sequence each person is added to.
Starts with
seq_.last_used_attimestamp or nullrequiredWhen it last received a post.
created_attimestamprequiredWhen it was made.
{
"id": "hook_1Hq2LxW9cVbN3mKpRtYs0a",
"object": "text_hook",
"name": "Calendly bookings",
"url": "https://usebluebot.com/h/th_8Rk2mQ4zN7wX1cVbL5pT9yHsQ2aVc0Ld",
"enabled": true,
"test_mode": true,
"mapping": {
"to": "{{body.payload.questions_and_answers.0.answer}}",
"text": "Hi {{body.payload.name}}, you’re booked for {{body.payload.scheduled_event.start_time}}. Text back if anything changes.",
"first_name": "{{body.payload.first_name}}",
"last_name": "{{body.payload.last_name}}",
"tags": "calendly"
},
"template_id": null,
"sequence_id": null,
"last_used_at": null,
"created_at": "2026-11-03T16:00:00.000Z"
}Errors
Every refusal has the same envelope and a page of its own. These are the ones this operation can give.
| Code | Status | What it means |
|---|---|---|
| 401 | The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API. | |
| 403 | The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope. | |
| 429 | Too many requests. A key may make 120 requests a minute. The RateLimit header says how many are left, and Retry-After how long to wait. | |
| 500 | Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe. | |
| 400 | Something in the request doesn’t fit: a missing or malformed field, a bad id, or a combination the endpoint refuses. details names each field. | |
| 404 | There is no such thing on this account. Ids are prefixed by kind, so a message id starts with msg_. | |
| 409 | The account has as many of something as it may have. | |
| 402 | The account’s plan isn’t active, so BlueBot isn’t taking new texts. Texts already queued wait and go once the plan is active again. | |
| 409 | The Idempotency-Key was used in the last 24 hours with a different request. A key stands for one request. |
Try it
Call this operation from the page with your own key. The key stays in this tab and is forgotten when you leave.