API Reference

API Reference

Complete list of all TextBubbles API endpoints. Base URL: https://api.textbubbles.com

Messages

MethodPathDescription
POST/v1/messagesSend a message
GET/v1/messagesList messages
GET/v1/messages/:idGet message status
POST/v1/messages/:id/unsendUnsend a message
PUT/v1/messages/:idEdit a message
POST/v1/messages/:id/reactionsSend tapback reaction
DELETE/v1/messages/:idSoft-delete a message
GET/v1/messages/scheduledList scheduled messages
DELETE/v1/messages/:id/scheduleCancel scheduled message

Capabilities

MethodPathDescription
GET/v1/capabilities/:phoneNumberCheck iMessage/SMS/FaceTime support

GET /v1/capabilities/:phoneNumber

Check which messaging channels are available for a recipient, along with their current Focus status and a recommended channel. Results are cached to avoid repeatedly probing Apple infrastructure.

Authentication: Requires Bearer token (Authorization: Bearer tb_xxxxx)

Path Parameters:

ParameterTypeDescription
phoneNumberstringRecipient phone number in E.164 format (e.g., +14155551234). Must start with + followed by 2–15 digits.

Example Request

curl https://api.textbubbles.com/v1/capabilities/+14155551234 \
  -H "Authorization: Bearer YOUR_API_KEY"

Example Response

{
  "success": true,
  "data": {
    "phoneNumber": "+14155551234",
    "capabilities": {
      "imessage": true,
      "sms": true,
      "facetime": true
    },
    "focused": false,
    "recommendedChannel": "imessage",
    "lastChecked": "2026-03-28T09:55:00.000Z",
    "cached": true
  },
  "requestId": "req_abc123"
}

When the recipient is currently in a Focus mode, the response also includes focusMode:

{
  "success": true,
  "data": {
    "phoneNumber": "+14155551234",
    "capabilities": { "imessage": true, "sms": true, "facetime": true },
    "focused": true,
    "focusMode": "Do Not Disturb",
    "recommendedChannel": "imessage",
    "lastChecked": "2026-03-28T09:55:00.000Z",
    "cached": false
  },
  "requestId": "req_abc123"
}

Response Fields

FieldTypeDescription
phoneNumberstringEchoes the queried phone number in E.164 format
capabilities.imessagebooleanRecipient is reachable via iMessage
capabilities.smsbooleanRecipient is reachable via SMS
capabilities.facetimebooleanRecipient is reachable via FaceTime (audio or video)
focusedbooleanWhether the recipient is currently in a Focus mode that may suppress notifications
focusModestringName of the active Focus mode (only present when focused is true)
recommendedChannelstringSuggested channel to use: "imessage" if iMessage is available, otherwise "sms"
lastCheckedstringISO 8601 timestamp of when capabilities were last refreshed
cachedbooleantrue if the response came from the capability cache, false if freshly probed

Errors

StatusCodeDescription
400INVALID_PHONE_NUMBERPhone number is not in E.164 format
401UNAUTHORIZEDMissing or invalid Bearer token
403FORBIDDENAPI key has no associated customer

Tip: Use this endpoint before calling POST /v1/messages when you want to branch your application logic based on whether the recipient supports iMessage effects, tapbacks, or FaceTime calls. The recommendedChannel field is a convenient default for the routing.preference on message send.

Numbers

MethodPathDescription
GET/v1/numbersList available sender addresses

GET /v1/numbers

List all phone numbers and email addresses available as valid from addresses for your account.

Authentication: Requires Bearer token (Authorization: Bearer tb_xxxxx)

Example Request

curl -H "Authorization: Bearer tb_xxxxx" https://api.textbubbles.com/v1/numbers

Example Response

{
  "success": true,
  "data": [
    {
      "phoneNumber": "+14155551234",
      "email": "user@icloud.com",
      "instanceName": "TextBubbles Service 001",
      "isDefault": true,
      "healthStatus": "healthy"
    },
    {
      "phoneNumber": "+19876543210",
      "email": null,
      "instanceName": "TextBubbles Service 002",
      "isDefault": false,
      "healthStatus": "healthy"
    }
  ]
}

Fields

FieldTypeDescription
phoneNumberstringE.164 phone number
emailstring | nulliMessage email or null
instanceNamestringFriendly name of the instance
isDefaultbooleanWhether this is the default sender when no from is specified
healthStatusstringOne of healthy, degraded, unhealthy, or unknown

Note: Use the phoneNumber or email values as the from field when sending messages to control which sender address is used.

Webhooks

MethodPathDescription
POST/v1/webhooksRegister a webhook
GET/v1/webhooks/listList your webhooks
GET/v1/webhooks/:idGet a single webhook
PATCH/v1/webhooks/:idUpdate a webhook
DELETE/v1/webhooks/:idDelete a webhook
POST/v1/webhooks/:id/testSend a test event to a webhook
POST/v1/webhooks/:id/rotate-secretRotate signing secret
GET / PUT / DELETE/v1/webhooksLegacy single-webhook endpoints (deprecated)
POST/v1/webhooks/test, /v1/webhooks/rotate-secretLegacy single-webhook endpoints (deprecated)

Health Check

MethodPathDescription
GET/healthService health check

The health check endpoint requires no authentication and is not rate-limited. It returns the overall service status along with individual dependency checks.

Response

{
  "status": "ok",
  "timestamp": "2026-04-10T12:00:00.000Z",
  "checks": {
    "database": { "status": "ok" },
    "redis": { "status": "ok" },
    "imessage": { "status": "ok" },
    "whatsapp": {
      "status": "not_enabled",
      "experimental": true
    }
  }
}

The top-level status is "ok" when the database and Redis are both reachable, or "degraded" if either is down. iMessage and WhatsApp statuses are reported for visibility but do not affect the top-level status.

SMS fallback is handled natively by the iMessage provider — when an iMessage send fails to a non-iMessage recipient, the provider automatically falls back to SMS via a connected iPhone. There is no separate SMS provider to monitor.

Instance Health Status

Each iMessage provider instance is independently monitored every 2 minutes. Instance health is stored as one of four values:

StatusMeaning
healthyInstance is reachable and fully functional
degradedInstance is reachable but has issues (see warnings below)
unhealthyInstance is unreachable or the health check failed
unknownInstance has not been checked yet

Instance Health Warnings

When an instance has degraded status, the response includes an array of warning strings describing what is wrong. The following conditions trigger warnings:

ConditionWarningImpact
Private API disabled”Private API is disabled”Typing indicators, reactions, read receipts, and FaceTime events will not work
Private API helper disconnected”Private API helper is not connected”Same features as above are unavailable; requires operator intervention to resolve
No iMessage account detected”No iMessage account detected”iMessage and FaceTime will not work on this instance
No iCloud account detected”No iCloud account detected”iMessage and FaceTime will not work on this instance; requires operator intervention to resolve

An instance can have multiple warnings at the same time. Warnings are cleared automatically when the next health check finds the condition resolved.

Error Codes

CodeHTTP StatusDescription
UNAUTHORIZED401Missing or invalid Bearer token
FORBIDDEN403API key has no associated customer
ADDRESS_NOT_AUTHORIZED403Sender address not authorized for this customer
NO_DEFAULT_ADDRESS400No authorized address configured for customer
VALIDATION_ERROR400Request body failed validation
INVALID_PHONE_NUMBER400Phone number not in E.164 format
NOT_FOUND404Resource not found
REPLY_NOT_FOUND404Reply target message not found
CHANNEL_NOT_SUPPORTED400Operation not supported on channel
NO_CHANNEL_AVAILABLE400Recipient not reachable
INVALID_RECIPIENT400Must provide exactly one of to or conversationId on send
CONVERSATION_NOT_FOUND404conversationId does not match any conversation for this customer
CONVERSATION_NOT_READY409Conversation has no provider chat yet; retry after the chat is created
GROUP_SMS_UNSUPPORTED400Group send is not supported on SMS; send to participants individually
INVALID_STATUS400Operation not valid for current message status
MISSING_EXTERNAL_ID400Message has no external provider ID
ALREADY_UNSENT409Message already unsent
ALREADY_DELETED409Message already deleted
WEBHOOK_NOT_FOUND404Webhook does not exist or does not belong to your customer
WEBHOOK_DUPLICATE409A webhook with this URL and event set already exists
WEBHOOK_NOT_CONFIGURED404No webhook registered (legacy single-webhook endpoints only)
NOT_SCHEDULED400Message is not in scheduled status
INVALID_SCHEDULED_AT400Invalid ISO 8601 datetime format
SCHEDULED_IN_PAST400Scheduled time is in the past
SCHEDULED_TOO_FAR400Scheduled time is more than 30 days away
DEPRECATED410Endpoint has been deprecated
RATE_LIMIT_EXCEEDED429Too many requests
PROVIDER_TIMEOUT504Upstream iMessage service timed out
EDIT_FAILED502Message edit could not be completed
IMESSAGE_SEND_FAILED500iMessage delivery error
INTERNAL_ERROR500Unexpected server error