Settle an unconfirmed text
An unconfirmed text is one the Mac took and couldn’t confirm before its lease ran out; it may have gone.
/v1/messages/{id}/resolve
An unconfirmed text is one the Mac took and couldn’t confirm before its lease ran out; it may have gone. Look at the conversation, then mark_sent if the person got it or send_again to queue a new text with the same words, files and metadata. BlueBot never sends one again on its own.
Needs a key with the messages:send scope.
Send an Idempotency-Key so a retry never acts twice.
Path parameters
idstringrequiredThe text’s id.
Starts with
msg_.
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
actionstringrequiredmark_sentwhen the person got it;send_againqueues a new text with the same words, files and metadata.One of
mark_sent,send_again.
Example
/v1/messages/msg_1Hq2LxW9cVbN3mKpRtYs0a/resolvecurl -X POST "https://usebluebot.com/api/v1/messages/msg_1Hq2LxW9cVbN3mKpRtYs0a/resolve" \
-H "Authorization: Bearer $BLUEBOT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0f6d8c2e-5b1a-4c7e-9d3f-2a8b6e1c4d70" \
-d '{
"action": "send_again"
}'Response
200: The settled text. For send_again, resent_message_id names the new one.
idstringrequiredA msg_ id.
Starts with
msg_.object"message"requireddirectionstringrequiredoutfor a text from your number,infor one to it.One of
out,in.statestringrequiredOut:
scheduled,queued,sending,sent,delivered,read,failed,unconfirmed,expired,canceled. In:received.One of
scheduled,queued,sending,sent,delivered,read,failed,unconfirmed,expired,canceled,received.tostring or nullrequiredWho it went to. For a text in, your own number when the Mac knows it. Null in a group chat.
fromstring or nullrequiredWho sent it. For a text out, your own number when the Mac knows it.
chat_idstring or nullrequiredThe group chat it is in; null for a one-to-one text.
Starts with
chat_.contact_idstring or nullrequiredThe person, or for a group text in, the member who sent it.
Starts with
ct_.conversation_idstringrequiredA conv_ id.
Starts with
conv_.textstring or nullrequiredThe words. Null for a files-only text, an unsent one, and after 30 days, when BlueBot deletes the words and keeps the facts.
text_deletedbooleanrequiredTrue once the words were deleted after 30 days.
filesarray of FilerequiredPictures and files on the text, in order.
Show its 12 fieldsHide its fields
idstringrequiredA file_ id.
Starts with
file_.object"file"requirednamestring or nullrequiredThe file name, as it was uploaded or as Messages named it.
content_typestringrequiredThe media type.
sizeintegerrequiredBytes.
kindstringrequiredWhat the file is, for showing it: an image, a video, audio, a voice memo, a PDF, a contact card or another file.
One of
image,video,audio,voice_memo,pdf,contact_card,file.statusstringrequiredreadywhen BlueBot has the bytes;waitingwhile the Mac uploads them (usually seconds);too_largefor an attachment over 25 MB, which the Mac never uploads;deletedonce 30 days have passed.One of
ready,waiting,too_large,deleted.urlstring or nullrequiredReads the file for an hour. Null unless
statusisready.url_expires_attimestamp or nullrequiredWhen
urlstops working.transcriptstring or nullrequiredFor a voice memo, the words the Mac transcribed on the device, when the owner turned transcription on.
transcript_languagestring or nullrequiredThe transcript’s language, such as
en-US.created_attimestamprequiredWhen BlueBot first knew of the file.
service_requestedstringrequiredWhat the caller asked for.
autouses the service of the newest chat with the person, else iMessage.One of
auto,imessage,sms.servicestring or nullrequiredWhat it went or came through. Null until it is sent.
One of
imessage,sms.sms_retrybooleanrequiredTrue when an iMessage that never went was sent again once as a regular text.
sourcestringrequiredWhat sent it. Texts read from Messages, including ones you typed by hand, are
mac.One of
api,zapier,make,n8n,pipedream,cli,mcp,hook,broadcast,sequence,inbox,autopilot,keyword,away,widget,assistant,test,mac.source_refstring or nullrequiredThe broadcast, sequence, hook, rule or template behind it, as an id. A text sent with
template_idcarries the template’stpl_id here.metadatamap of stringrequiredYour own data, echoed on the message and on every webhook about it: up to 20 keys of up to 40 characters, each a string of up to 500.
holdHold or nullrequiredA text that is accepted but can’t go yet carries a hold. Null when nothing holds it.
Show its 3 fieldsHide its fields
reasonstringrequiredWhy the text is waiting, checked in this order:
account_held(BlueBot paused the account),platform_stopped(BlueBot stopped all sending),plan_lapsed,paused(you paused sending),device_offline(no check-in from the Mac for 2 minutes),quiet_hours,daily_new_people_limit,platform_daily_limit(1,000 a day) andpacing(its turn in the spacing between texts).One of
account_held,platform_stopped,plan_lapsed,paused,device_offline,quiet_hours,daily_new_people_limit,platform_daily_limit,pacing.untiltimestamp or nullrequiredWhen it should stop waiting, when that is known: the end of quiet hours, the next local midnight, or the estimated slot.
descriptionstringrequiredThe hold in words.
send_attimestamp or nullrequiredFor a scheduled text, when it goes.
expires_attimestamp or nullrequiredA text still queued at this time expires.
failureobject or nullrequiredWhy a
failedtext didn’t go. Also set on asenttext when the words went and a file didn’t.Show its 2 fieldsHide its fields
reasonstringrequiredOne of
messages_refused,not_on_imessage,file_unavailable.detailstring or nullrequiredWhat the Mac saw, in words.
cancel_reasonstring or nullrequiredWhy it was canceled:
requested,opted_out(the person texted a stop word),sequence_stopped,broadcast_canceledorstaff.One of
requested,opted_out,sequence_stopped,broadcast_canceled,staff.resolutionstring or nullrequiredHow an
unconfirmedtext was settled: marked sent, or sent again as a new text.One of
marked_sent,resent.resolved_attimestamp or nullrequiredWhen it was settled.
resent_message_idstring or nullrequiredThe new text, when this one was sent again.
Starts with
msg_.reply_to_idstring or nullrequiredThe text this one answers inline, when Messages recorded one.
Starts with
msg_.reactionsarray of ReactionrequiredTapbacks on this text that are still there.
Show its 6 fieldsHide its fields
idstringrequiredA rxn_ id.
Starts with
rxn_.kindstringrequiredThe tapback: love, like, dislike, laugh, emphasize, question, or a custom emoji.
One of
love,like,dislike,laugh,emphasize,question,emoji.emojistring or nullrequiredThe emoji, for
kind: "emoji".fromstring or nullrequiredWho reacted; null when it was you, on your Mac or iPhone.
directionstringrequiredinfrom the other person,outfrom you.One of
in,out.added_attimestamprequiredWhen the tapback was added.
edited_attimestamp or nullrequiredWhen it was last edited in Messages.
unsent_attimestamp or nullrequiredWhen it was unsent in Messages.
created_attimestamprequiredWhen BlueBot accepted or first saw it.
queued_attimestamp or nullrequiredWhen it became due.
sending_attimestamp or nullrequiredWhen the Mac took it.
sent_attimestamp or nullrequiredWhen Messages showed it sent.
delivered_attimestamp or nullrequiredWhen iMessage showed it delivered. Regular texts are never delivered.
read_attimestamp or nullrequiredWhen it was read, where the person shares read receipts.
failed_attimestamp or nullrequiredWhen it failed.
unconfirmed_attimestamp or nullrequiredWhen the Mac’s lease lapsed without saying whether it went.
expired_attimestamp or nullrequiredWhen it expired.
canceled_attimestamp or nullrequiredWhen it was canceled.
received_attimestamp or nullrequiredFor a text in, when it arrived.
{
"id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
"object": "message",
"direction": "out",
"state": "unconfirmed",
"to": "+15555550123",
"from": "+15555550100",
"chat_id": null,
"contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
"conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
"text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
"text_deleted": false,
"files": [],
"service_requested": "auto",
"service": null,
"sms_retry": false,
"source": "api",
"source_ref": null,
"metadata": {
"crm_id": "48213"
},
"hold": null,
"send_at": null,
"expires_at": "2026-11-14T19:41:00.000Z",
"failure": null,
"cancel_reason": null,
"resolution": "resent",
"resolved_at": "2026-11-13T19:50:00.000Z",
"resent_message_id": "msg_3Lp3VsC7hGqE5tZyKbWn2d",
"reply_to_id": null,
"reactions": [],
"edited_at": null,
"unsent_at": null,
"created_at": "2026-11-13T19:41:00.000Z",
"queued_at": "2026-11-13T19:41:00.000Z",
"sending_at": "2026-11-13T19:41:02.000Z",
"sent_at": null,
"delivered_at": null,
"read_at": null,
"failed_at": null,
"unconfirmed_at": "2026-11-13T19:44:02.000Z",
"expired_at": null,
"canceled_at": null,
"received_at": null
}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 request doesn’t fit the thing’s current state, or another request with the same Idempotency-Key is still running. | |
| 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. |
Try it
Call this operation from the page with your own key. The key stays in this tab and is forgotten when you leave.