Skip to the page

API reference

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.

POST/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. Keys and scopes

Send an Idempotency-Key so a retry never acts twice. Idempotency

Path parameters

  • idstringrequired

    The text’s id.

    Starts with msg_.

Headers

  • Idempotency-Keystring

    Any 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

  • actionstringrequired

    mark_sent when the person got it; send_again queues a new text with the same words, files and metadata.

    One of mark_sent, send_again.

Example

POST/v1/messages/msg_1Hq2LxW9cVbN3mKpRtYs0a/resolveSettle an unconfirmed text →
curl -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.

  • idstringrequired

    A msg_ id.

    Starts with msg_.

  • object"message"required
  • directionstringrequired

    out for a text from your number, in for one to it.

    One of out, in.

  • statestringrequired

    Out: 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 nullrequired

    Who it went to. For a text in, your own number when the Mac knows it. Null in a group chat.

  • fromstring or nullrequired

    Who sent it. For a text out, your own number when the Mac knows it.

  • chat_idstring or nullrequired

    The group chat it is in; null for a one-to-one text.

    Starts with chat_.

  • contact_idstring or nullrequired

    The person, or for a group text in, the member who sent it.

    Starts with ct_.

  • conversation_idstringrequired

    A conv_ id.

    Starts with conv_.

  • textstring or nullrequired

    The words. Null for a files-only text, an unsent one, and after 30 days, when BlueBot deletes the words and keeps the facts.

  • text_deletedbooleanrequired

    True once the words were deleted after 30 days.

  • filesarray of Filerequired

    Pictures and files on the text, in order.

    Show its 12 fields
    • idstringrequired

      A file_ id.

      Starts with file_.

    • object"file"required
    • namestring or nullrequired

      The file name, as it was uploaded or as Messages named it.

    • content_typestringrequired

      The media type.

    • sizeintegerrequired

      Bytes.

    • kindstringrequired

      What 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.

    • statusstringrequired

      ready when BlueBot has the bytes; waiting while the Mac uploads them (usually seconds); too_large for an attachment over 25 MB, which the Mac never uploads; deleted once 30 days have passed.

      One of ready, waiting, too_large, deleted.

    • urlstring or nullrequired

      Reads the file for an hour. Null unless status is ready.

    • url_expires_attimestamp or nullrequired

      When url stops working.

    • transcriptstring or nullrequired

      For a voice memo, the words the Mac transcribed on the device, when the owner turned transcription on.

    • transcript_languagestring or nullrequired

      The transcript’s language, such as en-US.

    • created_attimestamprequired

      When BlueBot first knew of the file.

  • service_requestedstringrequired

    What the caller asked for. auto uses the service of the newest chat with the person, else iMessage.

    One of auto, imessage, sms.

  • servicestring or nullrequired

    What it went or came through. Null until it is sent.

    One of imessage, sms.

  • sms_retrybooleanrequired

    True when an iMessage that never went was sent again once as a regular text.

  • sourcestringrequired

    What 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 nullrequired

    The broadcast, sequence, hook, rule or template behind it, as an id. A text sent with template_id carries the template’s tpl_ id here.

  • metadatamap of stringrequired

    Your 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 nullrequired

    A text that is accepted but can’t go yet carries a hold. Null when nothing holds it.

    Show its 3 fields
    • reasonstringrequired

      Why 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) and pacing (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 nullrequired

      When it should stop waiting, when that is known: the end of quiet hours, the next local midnight, or the estimated slot.

    • descriptionstringrequired

      The hold in words.

  • send_attimestamp or nullrequired

    For a scheduled text, when it goes.

  • expires_attimestamp or nullrequired

    A text still queued at this time expires.

  • failureobject or nullrequired

    Why a failed text didn’t go. Also set on a sent text when the words went and a file didn’t.

    Show its 2 fields
    • reasonstringrequired

      One of messages_refused, not_on_imessage, file_unavailable.

    • detailstring or nullrequired

      What the Mac saw, in words.

  • cancel_reasonstring or nullrequired

    Why it was canceled: requested, opted_out (the person texted a stop word), sequence_stopped, broadcast_canceled or staff.

    One of requested, opted_out, sequence_stopped, broadcast_canceled, staff.

  • resolutionstring or nullrequired

    How an unconfirmed text was settled: marked sent, or sent again as a new text.

    One of marked_sent, resent.

  • resolved_attimestamp or nullrequired

    When it was settled.

  • resent_message_idstring or nullrequired

    The new text, when this one was sent again.

    Starts with msg_.

  • reply_to_idstring or nullrequired

    The text this one answers inline, when Messages recorded one.

    Starts with msg_.

  • reactionsarray of Reactionrequired

    Tapbacks on this text that are still there.

    Show its 6 fields
    • idstringrequired

      A rxn_ id.

      Starts with rxn_.

    • kindstringrequired

      The tapback: love, like, dislike, laugh, emphasize, question, or a custom emoji.

      One of love, like, dislike, laugh, emphasize, question, emoji.

    • emojistring or nullrequired

      The emoji, for kind: "emoji".

    • fromstring or nullrequired

      Who reacted; null when it was you, on your Mac or iPhone.

    • directionstringrequired

      in from the other person, out from you.

      One of in, out.

    • added_attimestamprequired

      When the tapback was added.

  • edited_attimestamp or nullrequired

    When it was last edited in Messages.

  • unsent_attimestamp or nullrequired

    When it was unsent in Messages.

  • created_attimestamprequired

    When BlueBot accepted or first saw it.

  • queued_attimestamp or nullrequired

    When it became due.

  • sending_attimestamp or nullrequired

    When the Mac took it.

  • sent_attimestamp or nullrequired

    When Messages showed it sent.

  • delivered_attimestamp or nullrequired

    When iMessage showed it delivered. Regular texts are never delivered.

  • read_attimestamp or nullrequired

    When it was read, where the person shares read receipts.

  • failed_attimestamp or nullrequired

    When it failed.

  • unconfirmed_attimestamp or nullrequired

    When the Mac’s lease lapsed without saying whether it went.

  • expired_attimestamp or nullrequired

    When it expired.

  • canceled_attimestamp or nullrequired

    When it was canceled.

  • received_attimestamp or nullrequired

    For a text in, when it arrived.

Response200
{
  "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.

CodeStatusWhat it means
unauthorized401The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API.
insufficient_scope403The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope.
rate_limited429Too 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.
internal500Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe.
invalid_request400Something in the request doesn’t fit: a missing or malformed field, a bad id, or a combination the endpoint refuses. details names each field.
not_found404There is no such thing on this account. Ids are prefixed by kind, so a message id starts with msg_.
conflict409The request doesn’t fit the thing’s current state, or another request with the same Idempotency-Key is still running.
plan_lapsed402The 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.