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

Receiving SMS

Learn how to receive and process incoming SMS messages using the textbee.dev API and webhooks.

textbee.dev forwards SMS messages sent to your registered Android device to your account. Use this for verification codes, customer inquiries, and two-way messaging.

Prerequisites

  • A textbee.dev account
  • A registered Android device
  • SMS receiving enabled in the app

Enabling SMS receiving

  1. Open the textbee.dev app on your Android device.
  2. Go to Settings or Receive SMS and turn Receive SMS (or Enable Receiving) ON.
  3. Incoming SMS will be forwarded to textbee.dev. You can confirm in the dashboard under Devices that receiving is enabled.

Recommended: use a webhook

For real-time handling of incoming SMS, set up a webhook. Your server gets a POST when each message is received - no polling needed.

  1. In the dashboard, go to Webhooks and add a webhook URL.
  2. Subscribe to the MESSAGE_RECEIVED event.
  3. Implement your endpoint to accept the payload and return 200.

Details, payload format, and signing: Webhooks.

Fetching message history (API)

To list received messages (e.g. for history or backfill), use the account-level message history endpoint with direction=received:

GET https://api.textbee.dev/api/v1/gateway/messages

Headers: x-api-key: YOUR_API_KEY

Query parameters:

  • direction (optional): all, sent, or received. Use received for incoming SMS only. Default: all.
  • deviceIds (optional): Comma-separated device ids to include. Default: every device on your account. Messages from deleted devices are not included.
  • smsBatchId (optional): Only messages from one batch, using the smsBatchId a send returns. Combine with status=failed to list the recipients of a batch that failed.
  • status (optional): Delivery state to return, e.g. failed or delivered.
  • search (optional): Match against the message text and the other party's number.
  • from / to (optional): Time window on when the platform stored the message. ISO-8601 with an explicit timezone (2026-08-01T00:00:00Z or +03:00 form), or a plain date (read as UTC midnight). from is inclusive, to is exclusive, so back-to-back windows never double-count a message. A datetime without a timezone is rejected.
  • order (optional): desc (default, newest first) or asc (oldest first).
  • page (optional): Page number. Default: 1.
  • limit (optional): Items per page. Default: 50, max: 100.
  • cursor (optional): Opaque position from a previous response's meta.nextCursor. Use it instead of page when polling.

Example (cURL):

curl -X GET "https://api.textbee.dev/api/v1/gateway/messages?direction=received&page=1&limit=50" \
  -H "x-api-key: YOUR_API_KEY"

The response includes a data array of messages and a meta object (page, limit, total, totalPages, plus nextCursor and hasMore). Each message includes fields such as _id, message, direction, sender, receivedAt, and device.

Polling for new messages

Webhooks are the push option; this is the reliable pull option. Ask for messages in ascending order from a starting time, then follow the cursor:

  1. First call: GET /gateway/messages?direction=received&order=asc&from=2026-08-01T00:00:00Z
  2. Follow meta.nextCursor until meta.hasMore is false.
  3. On the next poll, resume from the last nextCursor you saw.

The cursor is your resume token, so this never re-reads pages, never misses a message that arrived while you were reading, and never returns the same message twice. Prefer Z timestamps for rolling windows, and note that from/to filter on when the platform stored the message: a phone that was offline uploads its backlog later, and cursor polling still picks those up.

The device-scoped route (GET /gateway/devices/{DEVICE_ID}/messages) keeps working but is deprecated; new integrations should use /gateway/messages.

Next Steps

Need help? Check our FAQ or contact support.