curl --request POST \
--url https://api.blujay.io/v1/chats \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"from": "+15555550100",
"to": [
"+15555550123"
],
"message": {
"parts": [
{
"type": "text",
"text": "Hi Ava, this is Sam from the Northwind support team."
}
],
"idempotency_key": "first-send-001"
}
}
'{
"status": "success",
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17:01:00.000Z",
"data": {
"chat_id": "chat_abc123",
"message": {
"id": "msg_abc123",
"direction": "outbound",
"delivery_status": "queued",
"service": "iMessage",
"from": "+15555550100",
"to": [
"+15555550123"
],
"created_at": "2026-10-14T17:01:00.000Z",
"parts": [
{
"type": "text",
"text": "Hi Ava, this is Sam from the Northwind support team.",
"text_decorations": [
{
"range": [
1,
1
],
"style": "bold"
}
]
}
],
"preferred_service": "iMessage",
"reply_to": {
"message_id": "msg_abc123",
"part_index": 0,
"thread_root_message_id": "msg_abc123"
}
}
},
"client_request_id": "<string>"
}Create a chat and send the first message
Starts a chat from one of your Blujay numbers and sends its first message. One recipient in to creates a direct chat; two or more create a group chat.
For a direct chat you can leave out from, and Blujay picks the number. It uses the number this person already knows you on. If they’ve never texted any of your numbers, it uses your only number, or else the default line of the teammate the contact is assigned to. If none of those apply, the request returns 422 FROM_NUMBER_REQUIRED and Blujay never guesses. A group chat always needs from.
Blujay returns 202 as soon as the message is accepted and sends it in the background. Follow its progress with message webhooks or GET /v1/messages/{message_id}.
The first message has some limits (see the sending rules at https://docs.blujay.io/messaging/sending-rules):
- It can’t contain a link. A link part, or a URL in the text, returns
400 FIRST_MESSAGE_LINK_NOT_ALLOWED. Send links in follow-up messages after the contact replies. - Until the contact replies,
mediaandvcardparts return400 PRE_REPLY_CONTENT_BLOCKEDand text is limited to 300 characters (400 PRE_REPLY_LENGTH_EXCEEDED). A first message is text only. reply_toisn’t accepted (400 VALIDATION_ERROR), and message effects and text decorations return400 FEATURE_NOT_ENABLED.
Send an Idempotency-Key header (or message.idempotency_key) so you can safely retry. Repeating a request with the same key returns 200 with the original response instead of sending again.
Errors worth handling:
403 RECIPIENT_SUPPRESSED: the recipient opted out.403 CONTACT_NOT_VERIFIED: on the Free Plan, the contact hasn’t texted your Free Plan number to verify yet.403 CONTACT_MUST_TEXT_FIRST: the number is on the AI Agent plan: it only replies to people who text it first, and can’t send to group chats.422 FROM_NUMBER_REQUIRED: you left outfromand Blujay couldn’t tell which number to use.error.messagenames the fix, such as setting a default line for the assigned teammate in Team Members.429 RATE_LIMIT_EXCEEDEDor429 QUEUE_FULL: the sending number hit a limit. WaitRetry-Afterseconds. Each number’s current limits are inGET /v1/phone-numbersunderlimits.503 QUEUE_UNAVAILABLE: Blujay couldn’t accept the message right now. Retry with the sameIdempotency-Key.
curl --request POST \
--url https://api.blujay.io/v1/chats \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"from": "+15555550100",
"to": [
"+15555550123"
],
"message": {
"parts": [
{
"type": "text",
"text": "Hi Ava, this is Sam from the Northwind support team."
}
],
"idempotency_key": "first-send-001"
}
}
'{
"status": "success",
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17:01:00.000Z",
"data": {
"chat_id": "chat_abc123",
"message": {
"id": "msg_abc123",
"direction": "outbound",
"delivery_status": "queued",
"service": "iMessage",
"from": "+15555550100",
"to": [
"+15555550123"
],
"created_at": "2026-10-14T17:01:00.000Z",
"parts": [
{
"type": "text",
"text": "Hi Ava, this is Sam from the Northwind support team.",
"text_decorations": [
{
"range": [
1,
1
],
"style": "bold"
}
]
}
],
"preferred_service": "iMessage",
"reply_to": {
"message_id": "msg_abc123",
"part_index": 0,
"thread_root_message_id": "msg_abc123"
}
}
},
"client_request_id": "<string>"
}Authorizations
Your workspace API key, sent as Authorization: Bearer blu_.... Workspace admins can find it in the Blujay app under API.
An API key has full access to your workspace and works on every endpoint. There is no test mode: every key sends real messages and changes real data, so keep it secret and use it only from your server.
Each API key can make 600 read requests and 120 write requests per minute, plus 60 attachment requests per minute. Over a limit you get 429 RATE_LIMIT_EXCEEDED with Retry-After.
Headers
A unique value you choose (1–255 characters) that makes this request safe to retry. Send the same key with the same request and Blujay returns the original response instead of doing the work again. Use a new key for each new action.
Blujay keeps keys for at least 24 hours. Keys are separate for each API key and each route family (for example every POST /v1/chats/{chat_id}/messages shares one). Reusing a key with a different request returns 409 IDEMPOTENCY_REQUEST_MISMATCH. Sending it while the first request is still running returns 409 IDEMPOTENCY_IN_PROGRESS; retry shortly.
1 - 255Body
Recipient phone numbers in E.164 or US format. One recipient creates a direct chat; two or more create a group chat. Contact IDs and email addresses aren't accepted.
1 - 31 elementsShow child attributes
Show child attributes
Your Blujay number to send from, in E.164 (+15555550100) or US format ((555) 555-0100). Optional for a direct chat; Blujay then picks the number this person knows you on (see the operation description). Required for a group chat.
"+15555550100"
API keys only. Sends a 7th text in a row to a contact who hasn't responded, once. A later text before they respond still returns PRE_REPLY_LIMIT_REACHED. It never lifts PRE_REPLY_CONTENT_BLOCKED or PRE_REPLY_LENGTH_EXCEEDED, and connected apps such as Zapier can't use it.
Response
This Idempotency-Key was already used for the same request. The response is the original one, and nothing was sent again.
Wraps every successful response. The result is in data.
success ^trc_[A-Za-z0-9_-]+$"trc_8f2a1c0e4b7d"
"2026-10-14T17:01:00.000Z"
Show child attributes
Show child attributes
Your X-Request-ID header value, echoed back when you send one. Not included on the send responses (POST /v1/chats, POST /v1/chats/{chat_id}/messages, POST /v1/messages/{message_id}/retry); keep your own mapping from your request ID to the returned message ID there.