textbee Logotextbee.dev
Plans from $9.99/mo.View Plans
Documentation

API reference

Every public textbee API endpoint, generated from the OpenAPI spec. Also available as plain text for LLMs.

The base URL is https://api.textbee.dev. Every request is authenticated with an API key created in the dashboard, sent as the x-api-key header.

All endpoints

EndpointSummary
GET/api/v1/gateway/statsGet account totals
GET/api/v1/gateway/devicesList your devices
GET/api/v1/gateway/devices/{id}Get a device
POST/api/v1/gateway/send-smsSend an SMS
POST/api/v1/gateway/send-bulk-smsSend several SMS in one call
GET/api/v1/gateway/messagesList messages
GET/api/v1/gateway/devices/{id}/sms/{smsId}Get one message
GET/api/v1/gateway/devices/{id}/sms-batch/{smsBatchId}Get a send batch
GET/api/v1/webhooksList your webhook subscriptions
POST/api/v1/webhooksCreate a webhook subscription
GET/api/v1/webhooks/notificationsList webhook delivery attempts
GET/api/v1/webhooks/{webhookId}Get a webhook subscription
PATCH/api/v1/webhooks/{webhookId}Update a webhook subscription
DELETE/api/v1/webhooks/{webhookId}Delete a webhook subscription

gateway

Send SMS and read message history through the Android devices paired with your account.

GET/api/v1/gateway/stats

Get account totals

Messages sent, messages received, devices, and API keys across your whole account.

Response 200: Account totals.

Response 200 fields

FieldTypeDescription
datarequiredGatewayStatsDTOAccount totals.
data.totalSentSMSCountrequirednumberMessages sent across all your devices.
data.totalReceivedSMSCountrequirednumberMessages received across all your devices.
data.totalDeviceCountrequirednumberDevices on your account.
data.totalApiKeyCountrequirednumberAPI keys on your account.

Errors

StatusDescription
401Missing, invalid, or revoked API key.
curl "https://api.textbee.dev/api/v1/gateway/stats" \
  -H "x-api-key: YOUR_API_KEY"

GET/api/v1/gateway/devices

List your devices

Every phone paired with your account. The push token and hardware serial are never returned.

Response 200: Your devices.

Response 200 fields

FieldTypeDescription
datarequiredDeviceDTO[]Your devices.
data[]._idrequiredstringDevice id. Pass it as deviceId when sending.
data[].userrequiredstringOwner account id.
data[].enabledrequiredbooleanWhether the device may send and receive SMS. Sending to a disabled device fails.
data[].isDefaultrequiredbooleanWhether sends without a deviceId go out from this device.
data[].brandrequiredstringDevice brand.
data[].manufacturerrequiredstringDevice manufacturer.
data[].modelrequiredstringDevice model.
data[].namestringYour own label for the device.
data[].buildIdrequiredstringAndroid build id.
data[].osrequiredstringOperating system name.
data[].osVersionrequiredstringAndroid release version.
data[].osApiLevelnumberAndroid SDK level.
data[].osVersionSourcestringHow osVersion was determined. One of: reported, fingerprint, buildId.
data[].osBuildFingerprintstringAndroid build fingerprint.
data[].appVersionNamestringtextbee app version name.
data[].appVersionCodenumbertextbee app version code.
data[].sentSMSCountrequirednumberMessages this device has sent.
data[].receivedSMSCountrequirednumberMessages this device has received.
data[].heartbeatEnabledrequiredbooleanWhether the device reports heartbeats.
data[].heartbeatIntervalMinutesrequirednumberMinutes between heartbeats.
data[].receiveSMSEnabledrequiredbooleanWhether incoming messages are forwarded to textbee. Required for received message history and webhooks.
data[].smsSendDelaySecondsrequirednumberSeconds the device waits between messages in a batch.
data[].lastHeartbeatstringLast heartbeat. A device silent for long is likely offline and sends will queue.
data[].batteryInfoBatteryInfoDTOBattery level at the last heartbeat.
data[].batteryInfo.percentagenumberBattery level, 0 to 100.
data[].batteryInfo.isChargingbooleanWhether the device was charging at the last heartbeat.
data[].batteryInfo.lastUpdatedstringWhen this reading was taken.
data[].networkInfoNetworkInfoDTOConnection the device was on at the last heartbeat.
data[].networkInfo.networkTypestringConnection the device last reported. One of: wifi, cellular, none.
data[].networkInfo.lastUpdatedstringWhen this reading was taken.
data[].appVersionInfoAppVersionInfoDTOtextbee app version running on the device.
data[].appVersionInfo.versionNamestringtextbee app version name.
data[].appVersionInfo.versionCodenumbertextbee app version code.
data[].appVersionInfo.lastUpdatedstringWhen this reading was taken.
data[].deviceUptimeInfoDeviceUptimeInfoDTOHow long the device has been up.
data[].deviceUptimeInfo.uptimeMillisnumberMilliseconds since the device booted.
data[].deviceUptimeInfo.lastUpdatedstringWhen this reading was taken.
data[].memoryInfoMemoryInfoDTOMemory reported at the last heartbeat.
data[].memoryInfo.freeBytesnumberFree memory in bytes.
data[].memoryInfo.totalBytesnumberTotal memory in bytes.
data[].memoryInfo.maxBytesnumberMaximum memory the app may use, in bytes.
data[].memoryInfo.lastUpdatedstringWhen this reading was taken.
data[].storageInfoStorageInfoDTOStorage reported at the last heartbeat.
data[].storageInfo.availableBytesnumberFree storage in bytes.
data[].storageInfo.totalBytesnumberTotal storage in bytes.
data[].storageInfo.lastUpdatedstringWhen this reading was taken.
data[].systemInfoDeviceSystemInfoDTOTimezone and locale of the device.
data[].systemInfo.timezonestringDevice timezone.
data[].systemInfo.localestringDevice locale.
data[].systemInfo.lastUpdatedstringWhen this reading was taken.
data[].simInfoSimInfoCollectionDTOSIMs installed in the device.
data[].simInfo.lastUpdatedrequiredstringWhen the device last reported its SIM list.
data[].simInfo.simsrequiredSimInfoDTO[]SIMs currently installed in the device.
data[].createdAtrequiredstringWhen the device was registered.
data[].updatedAtrequiredstringWhen the device was last updated.

Errors

StatusDescription
401Missing, invalid, or revoked API key.
curl "https://api.textbee.dev/api/v1/gateway/devices" \
  -H "x-api-key: YOUR_API_KEY"

GET/api/v1/gateway/devices/{id}

Get a device

Full state of one device, including its last heartbeat, battery, and SIM list.

Path parameters

FieldTypeDescription
idrequiredstringDevice id, from GET /gateway/devices.

Response 200: The device.

Response 200 fields

FieldTypeDescription
datarequiredDeviceDTOThe device.
data._idrequiredstringDevice id. Pass it as deviceId when sending.
data.userrequiredstringOwner account id.
data.enabledrequiredbooleanWhether the device may send and receive SMS. Sending to a disabled device fails.
data.isDefaultrequiredbooleanWhether sends without a deviceId go out from this device.
data.brandrequiredstringDevice brand.
data.manufacturerrequiredstringDevice manufacturer.
data.modelrequiredstringDevice model.
data.namestringYour own label for the device.
data.buildIdrequiredstringAndroid build id.
data.osrequiredstringOperating system name.
data.osVersionrequiredstringAndroid release version.
data.osApiLevelnumberAndroid SDK level.
data.osVersionSourcestringHow osVersion was determined. One of: reported, fingerprint, buildId.
data.osBuildFingerprintstringAndroid build fingerprint.
data.appVersionNamestringtextbee app version name.
data.appVersionCodenumbertextbee app version code.
data.sentSMSCountrequirednumberMessages this device has sent.
data.receivedSMSCountrequirednumberMessages this device has received.
data.heartbeatEnabledrequiredbooleanWhether the device reports heartbeats.
data.heartbeatIntervalMinutesrequirednumberMinutes between heartbeats.
data.receiveSMSEnabledrequiredbooleanWhether incoming messages are forwarded to textbee. Required for received message history and webhooks.
data.smsSendDelaySecondsrequirednumberSeconds the device waits between messages in a batch.
data.lastHeartbeatstringLast heartbeat. A device silent for long is likely offline and sends will queue.
data.batteryInfoBatteryInfoDTOBattery level at the last heartbeat.
data.batteryInfo.percentagenumberBattery level, 0 to 100.
data.batteryInfo.isChargingbooleanWhether the device was charging at the last heartbeat.
data.batteryInfo.lastUpdatedstringWhen this reading was taken.
data.networkInfoNetworkInfoDTOConnection the device was on at the last heartbeat.
data.networkInfo.networkTypestringConnection the device last reported. One of: wifi, cellular, none.
data.networkInfo.lastUpdatedstringWhen this reading was taken.
data.appVersionInfoAppVersionInfoDTOtextbee app version running on the device.
data.appVersionInfo.versionNamestringtextbee app version name.
data.appVersionInfo.versionCodenumbertextbee app version code.
data.appVersionInfo.lastUpdatedstringWhen this reading was taken.
data.deviceUptimeInfoDeviceUptimeInfoDTOHow long the device has been up.
data.deviceUptimeInfo.uptimeMillisnumberMilliseconds since the device booted.
data.deviceUptimeInfo.lastUpdatedstringWhen this reading was taken.
data.memoryInfoMemoryInfoDTOMemory reported at the last heartbeat.
data.memoryInfo.freeBytesnumberFree memory in bytes.
data.memoryInfo.totalBytesnumberTotal memory in bytes.
data.memoryInfo.maxBytesnumberMaximum memory the app may use, in bytes.
data.memoryInfo.lastUpdatedstringWhen this reading was taken.
data.storageInfoStorageInfoDTOStorage reported at the last heartbeat.
data.storageInfo.availableBytesnumberFree storage in bytes.
data.storageInfo.totalBytesnumberTotal storage in bytes.
data.storageInfo.lastUpdatedstringWhen this reading was taken.
data.systemInfoDeviceSystemInfoDTOTimezone and locale of the device.
data.systemInfo.timezonestringDevice timezone.
data.systemInfo.localestringDevice locale.
data.systemInfo.lastUpdatedstringWhen this reading was taken.
data.simInfoSimInfoCollectionDTOSIMs installed in the device.
data.simInfo.lastUpdatedrequiredstringWhen the device last reported its SIM list.
data.simInfo.simsrequiredSimInfoDTO[]SIMs currently installed in the device.
data.createdAtrequiredstringWhen the device was registered.
data.updatedAtrequiredstringWhen the device was last updated.

Errors

StatusDescription
400The device id is not a valid id.
401Missing, invalid, or revoked API key.
404No device with that id on your account.
curl "https://api.textbee.dev/api/v1/gateway/devices/ID" \
  -H "x-api-key: YOUR_API_KEY"

POST/api/v1/gateway/send-sms

Send an SMS

Sends one message to one or more recipients from a phone on your account. deviceId is optional: without it textbee uses your default device, otherwise the enabled device with the most recent heartbeat. Every recipient counts as one message against your plan.

Request body

FieldTypeDescription
messagerequiredstringText of the message. Long messages are split by the carrier.
recipientsrequiredstring[]Phone numbers to send to, in international format. Each recipient is billed as one message.
simSubscriptionIdnumberSIM to send from, as subscriptionId from the device simInfo. Defaults to the device default SIM.
scheduledAtstringISO 8601 time to send the message. Must be in the future. Omit to send now.
deviceIdstringDevice to send from. When omitted, uses your default device, or the enabled device with the most recent heartbeat.

Response 200: The send was accepted. Use smsBatchId to follow delivery. Acceptance is not delivery: the phone still has to be online.

Response 200 fields

FieldTypeDescription
datarequiredSendSMSResultDTOOutcome of the send.
data.successbooleanWhether the batch was accepted. Queued sends only.
data.messagestringHuman readable outcome. Queued sends only.
data.smsBatchIdstringBatch id. Pass it to GET /gateway/devices/{id}/sms-batch/{smsBatchId} to follow delivery. Queued sends only.
data.recipientCountnumberNumber of recipients in the batch. Queued sends only.
data.successCountnumberMessages pushed to the device. Returned instead of the queue fields when the instance dispatches immediately.
data.failureCountnumberMessages that could not be pushed to the device.

Errors

StatusDescription
400No enabled device to send from, the device is disabled, your email is not verified, or the message could not be pushed to the phone.
401Missing, invalid, or revoked API key.
429Your daily, monthly, or per-batch plan limit is used up. The body says which one.
curl -X POST "https://api.textbee.dev/api/v1/gateway/send-sms" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "message": "Your appointment is confirmed for Tuesday at 10am.",
  "recipients": [
    "+12025550123",
    "+12025550124"
  ]
}'

POST/api/v1/gateway/send-bulk-sms

Send several SMS in one call

Sends a batch where every entry has its own text and recipients. deviceId is optional and resolves the same way as POST /gateway/send-sms.

Request body

FieldTypeDescription
messageTemplatestringOptional label for the batch. Each entry in messages carries its own text.
messagesrequiredSMSData[]Messages to send. Every message can target different recipients and use a different SIM.
messages[].messagerequiredstringText of the message. Long messages are split by the carrier.
messages[].recipientsrequiredstring[]Phone numbers to send to, in international format. Each recipient is billed as one message.
messages[].simSubscriptionIdnumberSIM to send from, as subscriptionId from the device simInfo. Defaults to the device default SIM.
messages[].scheduledAtstringISO 8601 time to send the message. Must be in the future. Omit to send now.
deviceIdstringDevice to send from. When omitted, uses your default device, or the enabled device with the most recent heartbeat.

Response 200: The batch was accepted.

Response 200 fields

FieldTypeDescription
datarequiredSendSMSResultDTOOutcome of the send.
data.successbooleanWhether the batch was accepted. Queued sends only.
data.messagestringHuman readable outcome. Queued sends only.
data.smsBatchIdstringBatch id. Pass it to GET /gateway/devices/{id}/sms-batch/{smsBatchId} to follow delivery. Queued sends only.
data.recipientCountnumberNumber of recipients in the batch. Queued sends only.
data.successCountnumberMessages pushed to the device. Returned instead of the queue fields when the instance dispatches immediately.
data.failureCountnumberMessages that could not be pushed to the device.

Errors

StatusDescription
400No enabled device to send from, the device is disabled, your email is not verified, or the batch could not be pushed to the phone.
401Missing, invalid, or revoked API key.
429Your daily, monthly, or per-batch plan limit is used up. The body says which one.
curl -X POST "https://api.textbee.dev/api/v1/gateway/send-bulk-sms" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "messages": [
    {
      "message": "Your appointment is confirmed for Tuesday at 10am.",
      "recipients": [
        "+12025550123",
        "+12025550124"
      ],
      "simSubscriptionId": 1,
      "scheduledAt": "2024-01-15T10:30:00Z"
    }
  ]
}'

GET/api/v1/gateway/messages

List messages

Sent and received messages across your whole account, newest first, with delivery status on each. Filter by device, direction, status, text, and time range. Two pagination modes: page numbers for browsing, or cursor for polling. To poll for new messages: request order=asc with a from timestamp, follow nextCursor until hasMore is false, then resume from the last nextCursor on the next poll. Time filters apply to createdAt (when the platform stored the message); for received messages this is upload time, which can lag the receivedAt shown on the message if the device was offline.

Query parameters

FieldTypeDescription
cursorstringOpaque position from a previous response nextCursor. Returns the page after that position and switches meta to nextCursor/hasMore without a total count.
limitintegerMessages per page. Default 50, maximum 100. Defaults to 50. Between 1 and 100.
pageintegerPage to return. Default 1. Mutually exclusive with cursor. Defaults to 1.
orderstringdesc (default) for newest first; asc to walk forward in time when polling. One of: desc, asc.
tostringExclusive upper bound on createdAt, same formats as from. Exclusive so consecutive windows never double-count a boundary message.
fromstringInclusive lower bound on createdAt. ISO-8601 with an explicit timezone (2026-08-01T00:00:00Z or +03:00 form), or a date (2026-08-01, read as UTC midnight). A datetime without a timezone is rejected.
searchstringMatch against the message text and the other party number. Encrypted messages cannot be searched.
statusstringDelivery state to return. Combine with direction: direction=sent&status=failed lists sends that failed. One of: pending, dispatched, sent, delivered, failed, unknown, received.
smsBatchIdstringOnly messages from this batch, using the smsBatchId returned by a send. Combine with status=failed to list the recipients of a batch that failed.
directionstringDirection to return. Default all. Matches the lowercase direction field on each message. Not the same as status: direction=sent means outbound, status=sent means the device dispatched it. One of: all, sent, received.
deviceIdsstringComma-separated device ids to include, from GET /gateway/devices. Default: all devices on the account. Messages from deleted devices are never included.

Response 200: A page of messages.

Response 200 fields

FieldTypeDescription
datarequiredMessageDTO[]Messages, newest first unless order=asc.
data[]._idrequiredstringMessage id.
data[].messagestringMessage text. Empty when the message is end to end encrypted.
data[].devicerequiredMessageDeviceDTODevice that sent or received the message.
data[].device._idrequiredstringDevice id.
data[].device.enabledrequiredbooleanWhether the device may send and receive SMS.
data[].device.brandrequiredstringDevice brand.
data[].device.modelrequiredstringDevice model.
data[].device.buildIdrequiredstringAndroid build id.
data[].statusstringDelivery state, lowercase. Incoming messages are always received. Outgoing messages move from pending to sent, then to delivered when the carrier confirms. Absent on messages stored before status tracking, so treat a missing value as unknown. One of: pending, dispatched, sent, delivered, failed, unknown, received.
data[].senderstringSender number. Set on received messages.
data[].recipientstringDestination number. Set on sent messages.
data[].smsBatchstringId of the batch this message was sent in.
data[].encryptedbooleanWhether the body is end to end encrypted. Encrypted bodies can only be read by your own client.
data[].simSubscriptionIdnumberSIM the message was sent from.
data[].receivedAtstringWhen the message was received. Received messages only.
data[].requestedAtstringWhen the send was requested. Sent messages only.
data[].dispatchedAtstringWhen the send job reached the device.
data[].sentAtstringWhen the device reported the message as sent.
data[].deliveredAtstringWhen the carrier confirmed delivery.
data[].failedAtstringWhen the message failed.
data[].errorCodestringFailure code reported by the device.
data[].errorMessagestringFailure reason reported by the device.
data[].createdAtrequiredstringWhen the record was created.
data[].updatedAtrequiredstringWhen the record was last updated.
data[].directionrequiredstringDirection of the message, lowercase. Values match the direction query filter, so a response value can be passed straight back as a filter. Not the same thing as status: direction=sent means outbound, status=sent means the device dispatched it. One of: sent, received.
data[].channelstringMessage channel. Currently always sms; mms will appear here when supported. Absent means sms. One of: sms.
metarequiredobjectPagination metadata. Page mode (no cursor) returns page, limit, total, totalPages plus nextCursor and hasMore; cursor mode returns limit, nextCursor, and hasMore only, skipping the expensive total count. anyOf rather than oneOf: a page-mode object also satisfies the cursor-mode shape, and oneOf would make strict validators reject it.

Errors

StatusDescription
400Invalid deviceIds, smsBatchId, direction, status, from, to, order, or cursor value. Unknown filter values fail rather than silently applying no filter.
401Missing, invalid, or revoked API key.
404A deviceIds entry or the smsBatchId is not on your account.
curl "https://api.textbee.dev/api/v1/gateway/messages?limit=50&page=1" \
  -H "x-api-key: YOUR_API_KEY"

GET/api/v1/gateway/devices/{id}/sms/{smsId}

Get one message

A single sent or received message with its delivery timestamps. Use it to check the outcome of one recipient.

Path parameters

FieldTypeDescription
idrequiredstringDevice id, from GET /gateway/devices.
smsIdrequiredstringMessage id, from the message history response.

Response 200: The message.

Response 200 fields

FieldTypeDescription
datarequiredRetrieveSMSDTOThe message.
data._idrequiredstringMessage id.
data.messagestringMessage text. Empty when the message is end to end encrypted.
data.devicerequiredMessageDeviceDTODevice that sent or received the message.
data.device._idrequiredstringDevice id.
data.device.enabledrequiredbooleanWhether the device may send and receive SMS.
data.device.brandrequiredstringDevice brand.
data.device.modelrequiredstringDevice model.
data.device.buildIdrequiredstringAndroid build id.
data.statusstringDelivery state, lowercase. Incoming messages are always received. Outgoing messages move from pending to sent, then to delivered when the carrier confirms. Absent on messages stored before status tracking, so treat a missing value as unknown. One of: pending, dispatched, sent, delivered, failed, unknown, received.
data.senderstringSender number. Set on received messages.
data.recipientstringDestination number. Set on sent messages.
data.smsBatchstringId of the batch this message was sent in.
data.encryptedbooleanWhether the body is end to end encrypted. Encrypted bodies can only be read by your own client.
data.simSubscriptionIdnumberSIM the message was sent from.
data.receivedAtstringWhen the message was received. Received messages only.
data.requestedAtstringWhen the send was requested. Sent messages only.
data.dispatchedAtstringWhen the send job reached the device.
data.sentAtstringWhen the device reported the message as sent.
data.deliveredAtstringWhen the carrier confirmed delivery.
data.failedAtstringWhen the message failed.
data.errorCodestringFailure code reported by the device.
data.errorMessagestringFailure reason reported by the device.
data.createdAtrequiredstringWhen the record was created.
data.updatedAtrequiredstringWhen the record was last updated.

Errors

StatusDescription
400The device id is not a valid id.
401Missing, invalid, or revoked API key.
404No such message on this device.
curl "https://api.textbee.dev/api/v1/gateway/devices/ID/sms/SMS_ID" \
  -H "x-api-key: YOUR_API_KEY"

GET/api/v1/gateway/devices/{id}/sms-batch/{smsBatchId}

Get a send batch

The batch returned by a send, plus one message per recipient. Poll this to see how a send is progressing.

Path parameters

FieldTypeDescription
idrequiredstringDevice id, from GET /gateway/devices.
smsBatchIdrequiredstringBatch id, returned as smsBatchId by the send endpoints.

Response 200: The batch and its messages.

Response 200 fields

FieldTypeDescription
datarequiredSMSBatchResultDTOThe batch and the messages in it.
data.batchrequiredSMSBatchDTOThe batch itself.
data.batch._idrequiredstringBatch id.
data.batch.userrequiredstringOwner account id.
data.batch.messagestringMessage text sent to every recipient in the batch.
data.batch.encryptedbooleanWhether the body is end to end encrypted.
data.batch.recipientCountrequirednumberRecipients in the batch.
data.batch.recipientPreviewstringShort preview of the recipient list.
data.batch.successCountrequirednumberMessages sent so far.
data.batch.failureCountrequirednumberMessages that failed.
data.batch.statusstringProgress of the batch as a whole, lowercase. Absent on batches stored before status tracking. sent and delivered appear on older batches that mirrored the per-message state. One of: pending, processing, completed, partial_success, failed, unknown, sent, delivered.
data.batch.errorstringFailure reason when the batch failed.
data.batch.completedAtstringWhen the batch finished.
data.batch.createdAtrequiredstringWhen the batch was created.
data.batch.updatedAtrequiredstringWhen the batch was last updated.
data.messagesrequiredRetrieveSMSDTO[]Every message in the batch, one per recipient.
data.messages[]._idrequiredstringMessage id.
data.messages[].messagestringMessage text. Empty when the message is end to end encrypted.
data.messages[].devicerequiredMessageDeviceDTODevice that sent or received the message.
data.messages[].statusstringDelivery state, lowercase. Incoming messages are always received. Outgoing messages move from pending to sent, then to delivered when the carrier confirms. Absent on messages stored before status tracking, so treat a missing value as unknown. One of: pending, dispatched, sent, delivered, failed, unknown, received.
data.messages[].senderstringSender number. Set on received messages.
data.messages[].recipientstringDestination number. Set on sent messages.
data.messages[].smsBatchstringId of the batch this message was sent in.
data.messages[].encryptedbooleanWhether the body is end to end encrypted. Encrypted bodies can only be read by your own client.
data.messages[].simSubscriptionIdnumberSIM the message was sent from.
data.messages[].receivedAtstringWhen the message was received. Received messages only.
data.messages[].requestedAtstringWhen the send was requested. Sent messages only.
data.messages[].dispatchedAtstringWhen the send job reached the device.
data.messages[].sentAtstringWhen the device reported the message as sent.
data.messages[].deliveredAtstringWhen the carrier confirmed delivery.
data.messages[].failedAtstringWhen the message failed.
data.messages[].errorCodestringFailure code reported by the device.
data.messages[].errorMessagestringFailure reason reported by the device.
data.messages[].createdAtrequiredstringWhen the record was created.
data.messages[].updatedAtrequiredstringWhen the record was last updated.

Errors

StatusDescription
400The device id is not a valid id.
401Missing, invalid, or revoked API key.
404No such batch on this device.
curl "https://api.textbee.dev/api/v1/gateway/devices/ID/sms-batch/SMS_BATCH_ID" \
  -H "x-api-key: YOUR_API_KEY"

webhooks

Subscribe to SMS events and inspect the delivery attempts textbee made for them.

GET/api/v1/webhooks

List your webhook subscriptions

Every subscription on your account, deleted ones excluded. Each one says which events it receives and where they are delivered.

Response 200: Your subscriptions.

Response 200 fields

FieldTypeDescription
datarequiredWebhookSubscriptionDTO[]Your webhook subscriptions. Deleted ones are not returned.
data[]._idrequiredstringSubscription id.
data[].userrequiredstringOwner account id.
data[].namestringLabel shown in the dashboard.
data[].isActiverequiredbooleanWhether deliveries are attempted. textbee pauses subscriptions that keep failing.
data[].eventsrequiredstring[]Events this subscription receives.
data[].deliveryUrlrequiredstringURL events are POSTed to.
data[].signingSecretrequiredstringSecret used to sign deliveries.
data[].successfulDeliveryCountrequirednumberDeliveries that succeeded.
data[].deliveryFailureCountrequirednumberDeliveries that failed.
data[].deliveryAttemptCountrequirednumberDelivery attempts made, retries included.
data[].lastDeliveryAttemptAtstringLast time a delivery was attempted.
data[].lastDeliverySuccessAtstringLast time a delivery succeeded.
data[].lastDeliveryFailureAtstringLast time a delivery failed.
data[].notesWebhookNoteDTO[]Notes textbee added, such as an auto-pause reason.
data[].notes[].atrequiredstringWhen the note was added.
data[].notes[].textrequiredstringWhat textbee recorded, for example why the subscription was paused.
data[].createdAtrequiredstringWhen the subscription was created.
data[].updatedAtrequiredstringWhen it was last updated.

Errors

StatusDescription
401Missing, invalid, or revoked API key.
curl "https://api.textbee.dev/api/v1/webhooks" \
  -H "x-api-key: YOUR_API_KEY"

POST/api/v1/webhooks

Create a webhook subscription

textbee POSTs the events you pick to your delivery URL and signs each request with your signing secret, sent as the X-Signature header. Failed deliveries are retried up to 10 times, and a subscription that keeps failing is paused.

Request body

FieldTypeDescription
namestringLabel shown in the dashboard. Up to 64 characters.
deliveryUrlrequiredstringURL textbee POSTs events to. Must be http or https and publicly reachable. Private and loopback hosts are rejected.
signingSecretrequiredstringShared secret, at least 20 characters. textbee signs every delivery with it and sends the signature in the X-Signature header, so your endpoint can verify the request really came from textbee.
eventsrequiredstring[]Events to deliver. At least one is required.

Response 201: The subscription was created.

Response 201 fields

FieldTypeDescription
datarequiredWebhookSubscriptionDTOThe subscription.
data._idrequiredstringSubscription id.
data.userrequiredstringOwner account id.
data.namestringLabel shown in the dashboard.
data.isActiverequiredbooleanWhether deliveries are attempted. textbee pauses subscriptions that keep failing.
data.eventsrequiredstring[]Events this subscription receives.
data.deliveryUrlrequiredstringURL events are POSTed to.
data.signingSecretrequiredstringSecret used to sign deliveries.
data.successfulDeliveryCountrequirednumberDeliveries that succeeded.
data.deliveryFailureCountrequirednumberDeliveries that failed.
data.deliveryAttemptCountrequirednumberDelivery attempts made, retries included.
data.lastDeliveryAttemptAtstringLast time a delivery was attempted.
data.lastDeliverySuccessAtstringLast time a delivery succeeded.
data.lastDeliveryFailureAtstringLast time a delivery failed.
data.notesWebhookNoteDTO[]Notes textbee added, such as an auto-pause reason.
data.notes[].atrequiredstringWhen the note was added.
data.notes[].textrequiredstringWhat textbee recorded, for example why the subscription was paused.
data.createdAtrequiredstringWhen the subscription was created.
data.updatedAtrequiredstringWhen it was last updated.

Errors

StatusDescription
400The delivery URL is unusable, the signing secret is shorter than 20 characters, the event list is empty or unknown, or you already have the maximum number of subscriptions.
401Missing, invalid, or revoked API key.
curl -X POST "https://api.textbee.dev/api/v1/webhooks" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "deliveryUrl": "https://example.com/textbee/webhook",
  "signingSecret": "SIGNING_SECRET",
  "events": [
    "MESSAGE_RECEIVED"
  ]
}'

GET/api/v1/webhooks/notifications

List webhook delivery attempts

Delivery history across your subscriptions, newest first. Use it to see what textbee sent, what your endpoint answered, and whether a retry is pending. History is kept for subscriptions you have since deleted.

Query parameters

FieldTypeDescription
pagenumberPage to return. Default 1.
limitnumberRecords per page. Default 10.
statusstringOnly return deliveries in this state. One of: pending, retrying, delivered, failed.
eventTypestringOnly return deliveries for this event. One of: MESSAGE_RECEIVED, MESSAGE_SENT, MESSAGE_DELIVERED, MESSAGE_FAILED, UNKNOWN_STATE, SMS_STATUS_UPDATED.
deviceIdstringOnly return deliveries for messages from this device.
startstringStart of the time range, ISO 8601. Applied only together with end.
endstringEnd of the time range, ISO 8601.
webhookSubscriptionIdstringOnly return deliveries for one subscription.

Response 200: A page of delivery records.

Response 200 fields

FieldTypeDescription
datarequiredWebhookNotificationPageDTODelivery records with pagination.
data.datarequiredWebhookNotificationDTO[]Delivery records, newest first.
data.data[]._idrequiredstringDelivery record id.
data.data[].webhookSubscriptionrequiredstringSubscription this belongs to.
data.data[].eventrequiredstringEvent that was delivered. One of: MESSAGE_RECEIVED, MESSAGE_SENT, MESSAGE_DELIVERED, MESSAGE_FAILED, UNKNOWN_STATE, SMS_STATUS_UPDATED.
data.data[].payloadrequiredobjectExact JSON body textbee POSTed to your endpoint.
data.data[].computedStatusrequiredstringDelivery state. Retrying means textbee will try again, failed means it gave up after 10 attempts. One of: pending, retrying, delivered, failed.
data.data[].deliveryUrlstringURL the delivery was sent to when it was attempted.
data.data[].deliveryAttemptCountrequirednumberAttempts made for this event.
data.data[].deliveredAtstringWhen your endpoint accepted the delivery.
data.data[].lastDeliveryAttemptAtstringWhen the last attempt was made.
data.data[].nextDeliveryAttemptAtstringWhen the next retry is due.
data.data[].deliveryAttemptAbortedAtstringWhen textbee stopped retrying.
data.data[].errorTypestringWhether the failure is worth retrying. One of: retryable, non-retryable.
data.data[].httpStatusCodenumberStatus code your endpoint returned on the last attempt.
data.data[].responseBodystringFirst 1000 characters of your endpoint response.
data.data[].idempotencyKeystringIdempotency key sent with the delivery.
data.data[].createdAtrequiredstringWhen the event was recorded.
data.metarequiredPaginationMetaDTOPagination info.
data.meta.pagerequiredintegerCurrent page number
data.meta.limitrequiredintegerNumber of items per page
data.meta.totalrequiredintegerTotal number of items
data.meta.totalPagesrequiredintegerTotal number of pages

Errors

StatusDescription
400deviceId or webhookSubscriptionId is not a valid id.
401Missing, invalid, or revoked API key.
404No webhook subscription with that id on your account.
curl "https://api.textbee.dev/api/v1/webhooks/notifications" \
  -H "x-api-key: YOUR_API_KEY"

GET/api/v1/webhooks/{webhookId}

Get a webhook subscription

One subscription with its delivery counters.

Path parameters

FieldTypeDescription
webhookIdrequiredstringSubscription id, from GET /webhooks.

Response 200: The subscription.

Response 200 fields

FieldTypeDescription
datarequiredWebhookSubscriptionDTOThe subscription.
data._idrequiredstringSubscription id.
data.userrequiredstringOwner account id.
data.namestringLabel shown in the dashboard.
data.isActiverequiredbooleanWhether deliveries are attempted. textbee pauses subscriptions that keep failing.
data.eventsrequiredstring[]Events this subscription receives.
data.deliveryUrlrequiredstringURL events are POSTed to.
data.signingSecretrequiredstringSecret used to sign deliveries.
data.successfulDeliveryCountrequirednumberDeliveries that succeeded.
data.deliveryFailureCountrequirednumberDeliveries that failed.
data.deliveryAttemptCountrequirednumberDelivery attempts made, retries included.
data.lastDeliveryAttemptAtstringLast time a delivery was attempted.
data.lastDeliverySuccessAtstringLast time a delivery succeeded.
data.lastDeliveryFailureAtstringLast time a delivery failed.
data.notesWebhookNoteDTO[]Notes textbee added, such as an auto-pause reason.
data.notes[].atrequiredstringWhen the note was added.
data.notes[].textrequiredstringWhat textbee recorded, for example why the subscription was paused.
data.createdAtrequiredstringWhen the subscription was created.
data.updatedAtrequiredstringWhen it was last updated.

Errors

StatusDescription
401Missing, invalid, or revoked API key.
404No webhook subscription with that id on your account.
curl "https://api.textbee.dev/api/v1/webhooks/WEBHOOK_ID" \
  -H "x-api-key: YOUR_API_KEY"

PATCH/api/v1/webhooks/{webhookId}

Update a webhook subscription

Changes only the fields you send. Use isActive to re-enable a subscription textbee paused after repeated failures.

Path parameters

FieldTypeDescription
webhookIdrequiredstringSubscription id, from GET /webhooks.

Request body

FieldTypeDescription
namestringLabel shown in the dashboard. Up to 64 characters.
isActivebooleanWhether deliveries are attempted. Set it to true to re-enable a subscription textbee paused after repeated failures.
deliveryUrlstringNew delivery URL. Same rules as on create: http or https, no private or loopback hosts.
signingSecretstringNew signing secret, at least 20 characters.
eventsstring[]Replacement event list. Cannot be empty.

Response 200: The updated subscription.

Response 200 fields

FieldTypeDescription
datarequiredWebhookSubscriptionDTOThe subscription.
data._idrequiredstringSubscription id.
data.userrequiredstringOwner account id.
data.namestringLabel shown in the dashboard.
data.isActiverequiredbooleanWhether deliveries are attempted. textbee pauses subscriptions that keep failing.
data.eventsrequiredstring[]Events this subscription receives.
data.deliveryUrlrequiredstringURL events are POSTed to.
data.signingSecretrequiredstringSecret used to sign deliveries.
data.successfulDeliveryCountrequirednumberDeliveries that succeeded.
data.deliveryFailureCountrequirednumberDeliveries that failed.
data.deliveryAttemptCountrequirednumberDelivery attempts made, retries included.
data.lastDeliveryAttemptAtstringLast time a delivery was attempted.
data.lastDeliverySuccessAtstringLast time a delivery succeeded.
data.lastDeliveryFailureAtstringLast time a delivery failed.
data.notesWebhookNoteDTO[]Notes textbee added, such as an auto-pause reason.
data.notes[].atrequiredstringWhen the note was added.
data.notes[].textrequiredstringWhat textbee recorded, for example why the subscription was paused.
data.createdAtrequiredstringWhen the subscription was created.
data.updatedAtrequiredstringWhen it was last updated.

Errors

StatusDescription
400The delivery URL is unusable, the signing secret is shorter than 20 characters, or the event list is empty or unknown.
401Missing, invalid, or revoked API key.
404No webhook subscription with that id on your account.
curl -X PATCH "https://api.textbee.dev/api/v1/webhooks/WEBHOOK_ID" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Order notifications",
  "isActive": true,
  "deliveryUrl": "https://example.com/textbee/webhook",
  "signingSecret": "SIGNING_SECRET",
  "events": [
    "MESSAGE_RECEIVED",
    "MESSAGE_DELIVERED"
  ]
}'

DELETE/api/v1/webhooks/{webhookId}

Delete a webhook subscription

Stops all deliveries for this subscription. Its delivery history stays readable through GET /webhooks/notifications.

Path parameters

FieldTypeDescription
webhookIdrequiredstringSubscription id, from GET /webhooks.

Response 200: The subscription was deleted.

Response 200 fields

FieldTypeDescription
datarequiredWebhookDeletedResultDTOOutcome of the delete.
data.successrequiredbooleanWhether the delete succeeded.

Errors

StatusDescription
401Missing, invalid, or revoked API key.
404No webhook subscription with that id on your account.
curl -X DELETE "https://api.textbee.dev/api/v1/webhooks/WEBHOOK_ID" \
  -H "x-api-key: YOUR_API_KEY"