# textbee, full documentation > The open-source SMS gateway for developers, automations, and AI agents. Turn an Android phone you already own into an SMS gateway and send or receive text messages over a simple REST API, with no per-message gateway fees. Generated from https://textbee.dev. Canonical HTML documentation: https://textbee.dev/docs Machine readable API spec: https://textbee.dev/openapi.json ## Contents - Overview - Setting up textbee - Registering a device - Reconnecting an old device - Sending SMS - Sending bulk SMS - Receiving SMS - JavaScript SDK - Webhooks - Pricing - FAQ - API reference ## Base URL and authentication Send and receive SMS through an Android phone you own. Authenticate every request with an API key from your textbee dashboard, sent as the x-api-key header. Base URL: https://api.textbee.dev API key from your textbee dashboard, sent on every request. # Overview Source: https://textbee.dev/docs Welcome to textbee.dev documentation. Learn how to transform your Android device into a powerful SMS gateway for your applications. Welcome to the textbee.dev documentation. Use this guide to send and receive SMS programmatically via your Android device. ## What is textbee.dev? textbee.dev is an open-source SMS gateway that uses your Android phone as the gateway. Control it through the [web dashboard](https://app.textbee.dev/dashboard) or REST API - no per-message fees from commercial providers; you use your existing phone plan. ## Key Benefits - **Cost-effective**: No per-message fees from third-party providers - **Easy integration**: Simple REST API works with any programming language - **Private and secure**: Your messages stay on your devices - **Open source**: Code available on [GitHub](https://github.com/textbee/textbee) - **Flexible**: Works with any application that can make HTTP requests ## Use Cases - **Notifications and alerts**: Order confirmations, appointment reminders, system alerts - **Two-factor authentication (2FA)**: Send OTP and verification codes via SMS - **Marketing campaigns**: Promotional messages (ensure compliance with local regulations) - **Customer communication**: Two-way SMS with customers - **Personal automation**: Reminders, IoT alerts, and similar use cases ## Getting Started 1. **[Set up textbee](/docs/getting-started/setting-up-textbee)** - Create your account and install the app 2. **[Register a device](/docs/getting-started/registering-a-device)** - Connect your Android phone 3. **[Send your first SMS](/docs/sending-sms/sending-sms)** - Start sending messages ## Documentation Structure - **Getting Started**: Setup guides and device registration - **Sending SMS**: Individual and bulk messages - **Receiving SMS**: Process incoming messages - **Webhooks**: Event-driven notifications - **Pricing**: Plan details and limits - **FAQ**: Common questions and answers ## Limitations - **Android only**: An Android phone is required as the SMS gateway; iOS is not supported. - **Phone must stay online**: The device needs an active internet connection (Wi‑Fi or mobile data) and should stay powered on. For a dedicated gateway, keep it plugged in. - **Message limits**: Free and Pro plans have monthly limits. See [Pricing](/docs/pricing) for details. - **Scheduled messages**: Not yet available. ## Reference - [API reference](/docs/api-reference): every public endpoint with parameters, fields, error codes, and curl examples - [OpenAPI spec](https://textbee.dev/openapi.json): the same reference as machine-readable OpenAPI 3 - [llms-full.txt](https://textbee.dev/llms-full.txt): all docs and the API reference in one plain-text file ## Need Help? - [Discord community](https://textbee.dev/discord) - [FAQ](/docs/faq) - [Status page](https://status.textbee.dev) - support@textbee.dev # Setting up textbee Source: https://textbee.dev/docs/getting-started/setting-up-textbee Learn how to create your textbee.dev account and install the Android app to get started with SMS gateway functionality. Create your textbee.dev account and install the Android app. You will then [register your device](/docs/getting-started/registering-a-device) by scanning a QR code or entering an API key from the dashboard (no sign-in inside the app). ## Prerequisites - Android device (Android 7.0 or higher) - Active mobile plan with SMS - Email address for your account - **Email verification is required** before you can send SMS ## Step 1: Create your account 1. Go to [textbee.dev](https://textbee.dev) and click **Register** or **Sign Up**. 2. Sign up with email and password or **Sign in with Google**. 3. **Verify your email** - check your inbox for the verification link. You must verify before sending SMS. ## Step 2: Download the Android app 1. On your Android phone, open [textbee.dev/download](https://textbee.dev/download) and download the APK. 2. If prompted, allow installation from unknown sources (**Settings** > **Security** > **Install unknown apps** - enable for your browser). 3. Open the APK and tap **Install**. ## Step 3: Grant permissions When you first open the app, click **Grant SMS permissions** and follow the prompts. **Tip:** For improved reliability, disable battery optimization for textbee (**Settings** > **Battery** > **Battery optimization** - set textbee to **Don’t optimize** or **Unrestricted**). ## Step 4: Register your device After installing and granting permissions, link the app to your account by **registering your device**: open the [dashboard](https://app.textbee.dev/dashboard), get the QR code or API key, then scan or enter it in the app. See **[Registering a device](/docs/getting-started/registering-a-device)** for the exact steps. ## Next steps 1. **[Register your device](/docs/getting-started/registering-a-device)** - Connect your phone via QR code or API key 2. **[Send your first SMS](/docs/sending-sms/sending-sms)** - Use the dashboard or API [FAQ](/docs/faq) | Contact support # Registering a device Source: https://textbee.dev/docs/getting-started/registering-a-device Connect your Android device using the app main screen: scan a QR code or enter your API key. Register your Android device so you can send SMS through your textbee.dev account. Open the app - the main screen has a device ID field, an API key field, a **Scan QR code** button, and a **Register** button. ## Prerequisites - textbee.dev account - textbee.dev Android app installed - SMS permission granted ## Option 1: QR code (recommended) 1. Go to [app.textbee.dev/dashboard](https://app.textbee.dev/dashboard), then click **Get started** or **Generate an API key**. A QR code appears. 2. Open the textbee.dev mobile app. On the first screen, tap **Scan QR code**. 3. Scan the QR code. The device registers automatically. 4. Check the dashboard; your device should show as **Active** with a Device ID. ## Option 2: API key 1. Go to [app.textbee.dev/dashboard](https://app.textbee.dev/dashboard), then click **Get started** or **Generate an API key**. Create a key if needed and copy it. 2. Open the textbee.dev mobile app. The first screen has the device ID and API key fields. Enter your API key and leave the device ID field **blank**. 3. Tap **Register**. 4. Check the dashboard; your device should show as **Active**. ## Next steps - [Send your first SMS](/docs/sending-sms/sending-sms) - [Receiving SMS](/docs/receiving-sms) - [Webhooks](/docs/webhooks) [FAQ](/docs/faq) | Contact support # Reconnecting an old device Source: https://textbee.dev/docs/getting-started/reconnecting-an-old-device Reconnect a device using the same flow as registering; use your existing device ID from the dashboard. Reconnecting uses the **same flow** as [registering a device](/docs/getting-started/registering-a-device). The only difference: you use your **existing device ID** from the dashboard (and your API key or a new QR code). You may need to reconnect if the device shows **Disconnected** or **Inactive** in the dashboard, or after reinstalling the app or resetting your phone. ## Option 1: Device ID + API key 1. Go to [app.textbee.dev/dashboard](https://app.textbee.dev/dashboard), open **Devices** and copy your device’s **Device ID**. Get your **API key** from the dashboard (Get started / Generate an API key) if needed. 2. Open the mobile app (first screen). Enter the **device ID** in the device ID field and your **API key** in the API key field. 3. Tap **Register** or **Update**. 4. Check the dashboard; the device should show as **Active**. ## Option 2: Device ID + scan QR 1. In the [dashboard](https://app.textbee.dev/dashboard), open **Devices** and copy your device’s **Device ID**. 2. Open the mobile app (first screen). Enter the **device ID** in the device ID field, then tap the **scan icon**. 3. In the dashboard, click **Get started** or **Generate an API key** so a new QR code is shown. 4. Scan that QR code with the app. The device reconnects. ## Troubleshooting - **Still disconnected** - Check internet, restart the app, confirm SMS permission, update the app. - **"Device limit reached"** - Free = 1 device, Pro = 5, Custom = unlimited. Remove unused devices or upgrade. - **Can’t find device** - Confirm you’re on the right account. If it was removed, register again as in [Registering a device](/docs/getting-started/registering-a-device). ## Next steps - [Send SMS](/docs/sending-sms/sending-sms) - [Webhooks](/docs/webhooks) [FAQ](/docs/faq) | Contact support # Sending SMS Source: https://textbee.dev/docs/sending-sms/sending-sms Learn how to send individual SMS messages using the textbee.dev API with code examples in multiple programming languages. Send SMS messages using the textbee.dev API from any application that can make HTTP requests. ## Prerequisites Before you begin, make sure you have: - ✅ A textbee.dev account - ✅ A registered Android device - ✅ Your Device ID (found in your dashboard) - ✅ An API key (generate one from your dashboard) ## API Endpoint ``` POST https://api.textbee.dev/api/v1/gateway/send-sms ``` By default, this sends from your default device, or your most recently active enabled device if you have not set one. To target a specific device instead, include an optional `deviceId` field in the request body. The previous device-scoped route (`/gateway/devices/{DEVICE_ID}/send-sms`) still works, but it is deprecated. ## Authentication Include your API key in the request headers: ``` x-api-key: YOUR_API_KEY ``` ## Request Body Send a JSON payload with the following structure: ```json { "recipients": ["+1234567890"], "message": "Hello, this is a test message!" } ``` ### Parameters - **recipients** (array, required): Array of phone numbers in E.164 format (e.g., `+1234567890`) - **message** (string, required): The SMS message text ### Optional fields - **simSubscriptionId** (number): Which SIM to use on multi‑SIM phones ## Code Examples Working in JavaScript or TypeScript? The official [`@textbee/sdk`](/docs/sdk/javascript) package wraps these calls with types and error handling, so you can skip the manual HTTP setup below. ### JavaScript/Node.js ```javascript const axios = require('axios'); const API_KEY = 'YOUR_API_KEY'; async function sendSMS(recipient, message) { const response = await axios.post( 'https://api.textbee.dev/api/v1/gateway/send-sms', { recipients: [recipient], message, // simSubscriptionId: 1, }, { headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY, }, } ); return response.data; } // Usage sendSMS('+1234567890', 'Hello from textbee.dev!'); ``` ### cURL ```bash curl -X POST \ https://api.textbee.dev/api/v1/gateway/send-sms \ -H 'Content-Type: application/json' \ -H 'x-api-key: YOUR_API_KEY' \ -d '{ "recipients": ["+1234567890"], "message": "Hello from textbee.dev!" }' ``` ## Phone Number Format Always use the E.164 format for phone numbers: - ✅ Correct: `+1234567890`, `+441234567890` - ❌ Incorrect: `1234567890`, `(123) 456-7890`, `123-456-7890` ## Next Steps - **[Use the JavaScript SDK](/docs/sdk/javascript)** - Typed client for Node.js and TypeScript - **[Send bulk SMS](/docs/sending-sms/sending-bulk-sms)** - Send to multiple recipients - **[Receive SMS](/docs/receiving-sms)** - Handle incoming messages - **[Set up webhooks](/docs/webhooks)** - Get real-time notifications Need help? Check our [FAQ](/docs/faq) or contact support. # Sending bulk SMS Source: https://textbee.dev/docs/sending-sms/sending-bulk-sms Learn how to send personalized SMS to multiple recipients using CSV upload in the textbee.dev dashboard. Send personalized bulk SMS by uploading a CSV file in the dashboard. ## Prerequisites - A textbee.dev account - A registered Android device ## CSV upload 1. Open the [dashboard](https://app.textbee.dev/dashboard) and go to the bulk SMS / CSV upload section. 2. Upload a CSV that has a phone number column and any extra columns you want in your message (e.g. name, orderId). Example CSV: ```csv phone,name,orderId +1234567890,John,1001 +0987654321,Jane,1002 ``` 3. Select your registered device. 4. Choose the **recipient column** (e.g. `phone`). 5. Write a message template using `{{ columnName }}` - each recipient gets a message with their row’s values: Example: `Hello {{ name }}, your order #{{ orderId }} is ready!` 6. Preview for a recipient to confirm the template, then send. ## Next Steps - **[Receive SMS](/docs/receiving-sms)** - Handle incoming messages - **[Set up webhooks](/docs/webhooks)** - Get real-time notifications for incoming messages - **[Check pricing](/docs/pricing)** - Plan details and limits Need help? Check our [FAQ](/docs/faq) or contact support. # Receiving SMS Source: https://textbee.dev/docs/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](https://app.textbee.dev/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](https://app.textbee.dev/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](/docs/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):** ```bash 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 - **[Set up webhooks](/docs/webhooks)** - Enable real-time notifications - **[Send SMS](/docs/sending-sms/sending-sms)** - Reply to received messages - **[Overview](/docs)** - Explore more capabilities Need help? Check our [FAQ](/docs/faq) or contact support. # JavaScript SDK Source: https://textbee.dev/docs/sdk/javascript Send SMS from Node.js and TypeScript with the official @textbee/sdk package, a zero dependency wrapper around the textbee.dev REST API. `@textbee/sdk` is the official JavaScript and TypeScript client for textbee.dev. It wraps the same REST API documented elsewhere in these docs, so anything you can do with the SDK you can also do with plain HTTP. It has zero dependencies, ships its own TypeScript types, and runs on Node 18 or newer, as well as Bun, Deno, Cloudflare Workers, and Vercel Edge. If you would rather call the API directly, see [Sending SMS](/docs/sending-sms/sending-sms). ## Install ```bash npm install @textbee/sdk ``` ## Quickstart Generate an API key from your [dashboard](https://textbee.dev/dashboard), then: ```js import { Textbee } from '@textbee/sdk' const textbee = new Textbee({ apiKey: process.env.TEXTBEE_API_KEY }) await textbee.sendSms({ recipients: ['+12025550123'], message: 'Hello from textbee!', }) ``` Never hardcode your API key. Read it from an environment variable so it stays out of your source control. ## Send options `sendSms` requires only `message` and `recipients`. The rest are optional. | Option | Type | Purpose | | --- | --- | --- | | `deviceId` | `string` | Which phone sends the message | | `simSubscriptionId` | `number` | Which SIM sends it on a multi-SIM phone | | `scheduledAt` | `string` or `Date` | Send later instead of now | ```js await textbee.sendSms({ recipients: ['+12025550123'], message: 'Your appointment is tomorrow at 9am', deviceId: '65f0000000000000000000aa', simSubscriptionId: 2, scheduledAt: new Date(Date.now() + 60 * 60 * 1000), }) ``` ### deviceId Leave it out and textbee chooses the sender for you: your default device first, and otherwise the enabled device with the most recent heartbeat. Pass one to force a specific phone. You can list your device ids with `getDevices()`. A malformed id fails the request rather than falling back to another phone, so a typo can never send from the wrong device. ### simSubscriptionId Find this value in the textbee Android app under **Dashboard**, in the **SIM Cards** section. Each SIM shows its subscription id next to it with a copy button. Leave it out and the phone decides: it uses the preferred SIM set in the app's settings, or the system default if none is set. Be aware that this value is not validated. If the id does not match a SIM currently in the phone it is ignored, and the message goes out from the preferred or default SIM instead. Nothing fails and no error is returned, so if the SIM matters, confirm which number the message arrived from. ### scheduledAt Accepts an ISO 8601 string or a `Date`. It must be in the future, and you can schedule up to 72 hours ahead. Omit it to send immediately. ## Devices ```js const devices = await textbee.getDevices() const device = await textbee.getDevice(deviceId) // Change which device handles sends that omit deviceId await textbee.setDefaultDevice(deviceId) ``` ## Message history and delivery status `getMessages` covers every device on the account, paginated, filterable, and searchable: ```js const { data, meta } = await textbee.getMessages({ direction: 'received', // 'all' | 'sent' | 'received' page: 1, limit: 50, search: 'invoice', }) console.log(meta.total, meta.totalPages) ``` Narrow it with any combination of filters: ```js // Specific devices, instead of the whole account await textbee.getMessages({ deviceIds: [deviceId] }) // Which recipients of a bulk send failed const { smsBatchId } = await textbee.sendSms({ recipients, message }) await textbee.getMessages({ smsBatchId, status: 'failed' }) // A date window. from is inclusive, to is exclusive, so back to back // windows never count a message twice. Datetimes need an explicit // timezone; a bare date is read as UTC midnight. await textbee.getMessages({ from: '2026-08-01', to: '2026-09-01' }) ``` ### Polling without duplicates Page numbers drift when new messages arrive mid-read. `iterateMessages` follows the pagination cursor instead, so every message is yielded exactly once: ```js for await (const message of textbee.iterateMessages({ direction: 'received', order: 'asc', from: lastRunTimestamp, })) { await handleMessage(message) } ``` Break out of the loop and it stops fetching. To resume on your next run, keep `meta.nextCursor` from `getMessages` and pass it back as `cursor`. To follow a single message or a whole batch: ```js // One message and its current status const sms = await textbee.getSms(deviceId, smsId) // A batch, using the smsBatchId returned by sendSms const { batch, messages } = await textbee.getSmsBatch(deviceId, smsBatchId) ``` ## Verifying webhooks textbee signs every webhook delivery with HMAC-SHA256 and sends the hex digest in the `X-Signature` header. The SDK ships a helper so you do not have to implement the comparison yourself. Pass the **raw request body** rather than a re-serialized object whenever your framework exposes it. Re-serializing a parsed object usually produces the same bytes, but not always, and a mismatch there looks like an invalid signature. ```js import { verifyWebhookSignature } from '@textbee/sdk' app.post( '/webhooks/textbee', express.raw({ type: 'application/json' }), async (req, res) => { const valid = await verifyWebhookSignature({ payload: req.body.toString('utf8'), signature: req.get('x-signature'), signingSecret: process.env.TEXTBEE_WEBHOOK_SECRET, }) if (!valid) return res.sendStatus(401) const event = JSON.parse(req.body.toString('utf8')) // handle the event res.sendStatus(200) }, ) ``` See [Webhooks](/docs/webhooks) for the event types and payload shapes. ## Handling errors Any non-2xx response throws a `TextbeeError` carrying the HTTP status and the parsed response body. Network failures reject with the underlying `fetch` error instead, so you can tell the two apart. ```js import { TextbeeError } from '@textbee/sdk' try { await textbee.sendSms({ recipients: ['+12025550123'], message: 'hi' }) } catch (error) { if (error instanceof TextbeeError) { console.error(error.status, error.message) } else { throw error } } ``` ## Client options ```js new Textbee({ apiKey: 'your-api-key', baseUrl: 'https://api.textbee.dev/api/v1', // override for self-hosted instances }) ``` ## What the SDK does not cover yet The SDK currently focuses on sending and reading messages. Bulk sending and some device management operations are REST only for now. Use the [Sending bulk SMS](/docs/sending-sms/sending-bulk-sms) guide for those. ## Links - Package on npm: [@textbee/sdk](https://www.npmjs.com/package/@textbee/sdk) - Source and issues: [github.com/textbee/textbee-js](https://github.com/textbee/textbee-js) # Webhooks Source: https://textbee.dev/docs/webhooks Learn how to configure and use webhooks to receive real-time notifications for SMS events in textbee.dev. Supports multiple webhook endpoints per account. Webhooks let textbee.dev notify your server in real time when events happen, so you don’t need to poll the API. ## What are Webhooks? Webhooks are HTTP callbacks that textbee.dev sends to your server when specific events occur. This enables event-driven architectures and real-time integrations. ## Supported Events textbee.dev supports the following webhook events: - **MESSAGE_RECEIVED**: When an SMS is received on your device - **MESSAGE_SENT**: When an SMS has been sent from your device - **MESSAGE_DELIVERED**: When an SMS has been delivered to the recipient - **MESSAGE_FAILED**: When sending an SMS has failed ## Setting Up Webhooks Set up webhooks in the dashboard. You need a public URL that accepts HTTP POST requests and returns 200 to acknowledge receipt. You can register multiple webhook endpoints on the same account: for example one for production, one for a staging integration, and one for your CRM. Each endpoint has its own signing secret and event subscriptions. 1. Open the [dashboard](https://app.textbee.dev/dashboard) and go to **Webhooks** (or **Settings** > **Webhooks**). 2. Click **Add Webhook** or **Create Webhook**. 3. (Optional) Give the webhook a short **name** so you can tell your endpoints apart. 4. Enter your webhook URL (use HTTPS in production). Private/loopback hosts (e.g. `localhost`, `127.0.0.1`, RFC1918 ranges) are rejected. 5. Select the events you want: **MESSAGE_RECEIVED**, **MESSAGE_SENT**, **MESSAGE_DELIVERED**, **MESSAGE_FAILED** (or a subset). 6. (Recommended) Set a **signing secret** (at least 20 characters) for signature verification. 7. Save. textbee.dev will send POST requests to your URL when the selected events occur. If multiple webhooks subscribe to the same event, each one receives its own independent delivery. ## Webhook Payloads Payloads are JSON with `event`, `timestamp`, and `data`. Return 200 quickly and process in the background if needed. ### MESSAGE_RECEIVED ```json { "event": "MESSAGE_RECEIVED", "timestamp": "2026-01-20T10:30:00Z", "data": { "_id": "abc123", "sender": "+1234567890", "message": "Hello!", "receivedAt": "2025-01-15T10:30:00Z", "device": { "_id": "device123", "enabled": true, "model": "Pixel 7" }, "createdAt": "2025-01-15T10:30:01Z", "updatedAt": "2025-01-15T10:30:01Z" } } ``` ### MESSAGE_SENT Sent when an SMS has been sent from your device. `data` includes message id, recipient(s), and device info. ### MESSAGE_DELIVERED Sent when the carrier reports delivery. `data` includes message id, recipient, and delivery time. ### MESSAGE_FAILED Sent when sending failed. `data` includes message id, recipient, and error details. ## Webhook Security ### Signature Verification To verify that webhooks are coming from textbee.dev, use signature verification: 1. When creating a webhook, set a **secret** (a random string) 2. textbee.dev will include a signature in the `X-Signature` header 3. Verify the signature on your server using the secret configured for that specific webhook If you have multiple webhooks, each one has its own signing secret. Use the secret that matches the receiving endpoint. ### Example: Signature Verification ```javascript const crypto = require('crypto'); function verifyWebhookSignature(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(JSON.stringify(payload)) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) ); } app.post('/webhook/textbee', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-signature']; const secret = process.env.WEBHOOK_SECRET; if (!verifyWebhookSignature(req.body, signature, secret)) { return res.status(401).json({ error: 'Invalid signature' }); } const payload = JSON.parse(req.body); // Process webhook... res.status(200).json({ success: true }); }); ``` ## Webhook Handler Examples ### Node.js/Express ```javascript const express = require('express'); const app = express(); app.use(express.json()); app.post('/webhook/textbee', (req, res) => { const { event, data } = req.body; switch (event) { case 'MESSAGE_RECEIVED': console.log(`Received from ${data.sender}: ${data.message}`); break; case 'MESSAGE_SENT': console.log(`Sent to ${data.recipient}`); break; case 'MESSAGE_DELIVERED': console.log(`Delivered to ${data.recipient}`); break; case 'MESSAGE_FAILED': console.error(`Failed to ${data.recipient}: ${data.error}`); break; default: console.log(`Event: ${event}`); } res.status(200).json({ success: true }); }); app.listen(3000, () => { console.log('Webhook server listening on port 3000'); }); ``` ### Python/Flask ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/webhook/textbee', methods=['POST']) def webhook(): payload = request.json event = payload.get('event') data = payload.get('data') or {} if event == 'MESSAGE_RECEIVED': print(f"Received from {data.get('sender')}: {data.get('message')}") elif event == 'MESSAGE_SENT': print(f"Sent to {data.get('recipient')}") elif event == 'MESSAGE_DELIVERED': print(f"Delivered to {data.get('recipient')}") elif event == 'MESSAGE_FAILED': print(f"Failed to {data.get('recipient')}: {data.get('error')}") return jsonify({'success': True}), 200 if __name__ == '__main__': app.run(port=3000) ``` ## Webhook Retries If your webhook endpoint returns a non-2xx status code, the delivery attempt is considered failed. ## Best Practices 1. **Always return 200 OK** immediately after receiving a webhook (process asynchronously if needed) 2. **Implement idempotency** - handle duplicate webhooks gracefully 3. **Verify webhook signatures** to ensure authenticity 4. **Use HTTPS** for webhook URLs in production 5. **Log all webhook events** for debugging and auditing 6. **Handle errors gracefully** - don't let webhook processing crash your server 7. **Process webhooks asynchronously** if processing takes time 8. **Monitor webhook delivery** - set up alerts for failed webhooks ## Next Steps - **[Receiving SMS](/docs/receiving-sms)** - Process incoming messages with webhooks - **[Sending SMS](/docs/sending-sms/sending-sms)** - Reply to received messages - **[Overview](/docs)** - Explore capabilities Need help? Check our [FAQ](/docs/faq) or contact support. # Pricing Source: https://textbee.dev/docs/pricing Learn about textbee.dev pricing plans, features, and message limits for Free, Pro, and Custom plans. textbee.dev offers flexible pricing plans to suit different needs, from individual developers to large enterprises. ## Pricing Plans ### Free Plan Perfect for getting started and testing textbee.dev. **Price**: $0/month **Features**: - Send and receive SMS messages - Register 1 active device - Max 50 messages per day - Up to 300 messages per month - Up to 50 recipients in bulk SMS - Webhook notifications - Basic support **Best for**: Testing, personal projects, low-volume applications ### Pro Plan Ideal for businesses and serious users who need more capacity. **Price**: $9.99/month (monthly) or $99.99/year (save 17%) **Features**: - Everything in Free plan - Register up to 5 active devices - Unlimited daily messages - Up to 5,000 messages per month - No bulk SMS recipient limits - Message templates with variables - Scheduled messages - Advanced analytics - Priority support **Best for**: Small businesses, startups, moderate-volume applications ### Custom Plan Tailored solutions for high-volume needs and specific requirements. **Price**: Contact sales for custom pricing **Features**: - Everything in Pro plan - Unlimited devices - Custom message volume limits - White-labeled solution - Custom integrations - SLA with uptime guarantees - Dedicated account manager - Volume discounts **Best for**: Enterprises, high-volume applications, custom requirements ## Message Limits Explained ### Daily Limits - **Free**: 50 messages per day (resets at midnight UTC) - **Pro/Custom**: Unlimited daily messages ### Monthly Limits - **Free**: 300 messages per month (resets on the 1st of each month) - **Pro**: 5,000 messages per month - **Custom**: Custom limits based on your needs ### What Happens When You Exceed Limits? - You'll receive a notification when approaching your limit - You'll receive another notification when you exceed your limit - Messages will be queued or rejected (depending on the limit type) - You can upgrade your plan to increase limits ## Bulk SMS Limits - **Free Plan**: Up to 50 recipients per bulk SMS request - **Pro Plan**: Unlimited recipients per request (subject to monthly message limits) - **Custom Plan**: Custom limits ## Device Limits - **Free Plan**: 1 active device - **Pro Plan**: Up to 5 active devices - **Custom Plan**: Unlimited devices Multiple devices help with: - **Throughput**: Send more messages simultaneously - **Redundancy**: If one device goes offline, others can continue - **Load distribution**: Distribute message load across devices ## API Rate Limits API requests are rate-limited to protect the service. Sending a very large burst of requests in a short time can return a 429 Too Many Requests response; wait briefly and retry. For normal integrations the limits that matter are your plan's message quotas. ## Upgrading Your Plan ### From Free to Pro 1. Go to your [dashboard](https://app.textbee.dev/dashboard) 2. Navigate to **"Billing"** or **"Plans"** 3. Click **"Upgrade to Pro"** 4. Complete the checkout process 5. Your plan will be upgraded immediately ### From Pro to Custom 1. Contact sales at sales@textbee.dev 2. Discuss your requirements 3. Receive a custom quote 4. Complete the upgrade process ## Billing ### Payment Methods - Credit card (Visa, Mastercard, American Express, UnionPay, JCB, Discover) - CashApp ### Billing Cycles - **Monthly**: Billed every month on your signup date - **Yearly**: Billed once per year (save 17% vs monthly) ### Cancellation - Cancel anytime from your dashboard - No cancellation fees - Access to Pro features until the end of your billing period - 7-day money-back guarantee for new Pro subscriptions ## Refunds We offer a 7-day money-back guarantee for new Pro plan subscriptions. Contact support@textbee.dev for refund requests. ## Enterprise Features (Custom Plan) ### White-labeling Remove textbee.dev branding and use your own branding throughout the platform. ### Custom Integrations Work with our team to create custom integrations for your specific needs. ### SLA Guarantees - 99.9% uptime guarantee - Response time guarantees - Support SLA ### Dedicated Account Manager Get a dedicated account manager to help with: - Onboarding and setup - Technical support - Best practices - Custom requirements ## Frequently Asked Questions ### Can I change plans anytime? Yes, you can upgrade or downgrade your plan at any time from your dashboard. ### What happens to my messages if I downgrade? If you downgrade and exceed your new plan's limits, you'll need to upgrade again or wait until limits reset. ### Do unused messages roll over? No, message limits reset at the start of each billing cycle (monthly or daily, depending on the limit type). ### Can I get a refund? Yes, we offer a 7-day money-back guarantee for new Pro plan subscriptions. ### Are there any setup fees? No, there are no setup fees for any plan. ## Next Steps - **[Get started](/docs/getting-started/setting-up-textbee)** - Create your free account - **[Overview](/docs)** - See what's included - **[Contact sales](mailto:sales@textbee.dev)** - Discuss custom plan options Have questions? Check our [FAQ](/docs/faq) or contact support. # FAQ Source: https://textbee.dev/docs/faq Frequently asked questions about textbee.dev SMS gateway, setup, usage, and troubleshooting. ## General Questions ### What is textbee.dev? textbee.dev is an SMS gateway service that turns your Android device into a powerful messaging platform. Instead of using expensive SMS API services, you can use your existing Android phone and mobile plan to send and receive text messages through a simple REST API. ### How does textbee.dev work? 1. Install the textbee.dev Android app on your device 2. Register your device with your textbee.dev account 3. Use the REST API to send SMS messages through your device 4. Receive SMS messages sent to your device's phone number ### Is textbee.dev free? Yes! We offer a free plan with generous limits: - 1 active device - 50 messages per day - 300 messages per month - Basic features ### What devices are supported? textbee.dev works with Android devices running Android 7.0 (Nougat) or higher. ### Do I need a special mobile plan? No, you can use your existing mobile plan. textbee.dev uses your plan's SMS allowance, so there are no additional per-message fees from third-party providers. ## Setup & Installation ### How do I get started? 1. Create an account at [textbee.dev](https://textbee.dev) 2. Download and install the Android app 3. Register your device 4. Start sending SMS via the API See our [getting started guide](/docs/getting-started/setting-up-textbee) for detailed instructions. ### How do I register my device? You can register your device using: - **QR Code** (recommended): Scan a QR code from your dashboard - **API Key**: Enter an API key manually in the app See our [device registration guide](/docs/getting-started/registering-a-device) for details. ### Can I use multiple devices? Yes! The number of devices depends on your plan: - **Free**: 1 device - **Pro**: Up to 5 devices - **Custom**: Unlimited devices ### What permissions does the app need? The app requires: - **SMS permissions**: To send and receive SMS messages - **Phone permissions**: To read your phone number - **Internet permissions**: To communicate with textbee.dev servers ## Usage & Features ### How do I send SMS messages? Use the REST API to send SMS messages. See our [sending SMS guide](/docs/sending-sms/sending-sms) for code examples. ### Can I send bulk SMS? Yes! You can send messages to multiple recipients at once. See our [bulk SMS guide](/docs/sending-sms/sending-bulk-sms) for details. **Limits**: - **Free**: Up to 50 recipients per request - **Pro/Custom**: Unlimited recipients ### How do I receive SMS messages? 1. Enable SMS receiving in the app settings 2. Retrieve messages via API or set up webhooks for real-time notifications See our [receiving SMS guide](/docs/receiving-sms) for details. ### What are webhooks? Webhooks allow you to receive real-time notifications when SMS events occur (message sent, delivered, received, etc.). See our [webhooks guide](/docs/webhooks) for setup instructions. ### Can I schedule messages? Yes. Pass a `scheduledAt` timestamp (ISO 8601, up to 72 hours ahead) when sending via the API or SDK. Scheduled messages are available on paid plans (Pro and above). ### Do you support message templates? Bulk sends support personalization with `{{ variable }}` templates: upload a CSV from the dashboard and reference its columns in your message. Reusable saved templates are coming soon. ## Pricing & Limits ### What are the message limits? **Free Plan**: - 50 messages per day - 300 messages per month **Pro Plan**: - Unlimited daily messages - 5,000 messages per month **Custom Plan**: - Custom limits based on your needs ### What happens if I exceed my limits? You'll receive notifications when approaching or exceeding limits. Messages may be queued or rejected depending on the limit type. You can upgrade your plan to increase limits. ### Can I upgrade or downgrade my plan? Yes, you can change your plan at any time from your dashboard. ### Do unused messages roll over? No, message limits reset at the start of each billing cycle. ### Is there a free trial? Yes! The Free plan is always free with no credit card required. ### What's your refund policy? We offer a 7-day money-back guarantee for new Pro plan subscriptions. ## Technical Questions ### What programming languages are supported? textbee.dev works with any programming language that can make HTTP requests. We provide examples for: - JavaScript/Node.js - Python - PHP - cURL - And more ### What's the API rate limit? The limits that matter for most integrations are your plan's message quotas (per day and per month). In addition, sending a very large burst of API requests in a short time can return a 429 Too Many Requests response. Wait briefly and retry with backoff. ### Do you have an API documentation? Yes! Visit [textbee.dev/docs](https://textbee.dev/docs) for complete API documentation. ### How do I handle errors? The API returns standard HTTP status codes: - **200**: Success - **400**: Bad Request (invalid parameters) - **401**: Unauthorized (invalid API key) - **404**: Not Found (device not found) - **429**: Too Many Requests (rate limit exceeded) - **500**: Internal Server Error See our [sending SMS guide](/docs/sending-sms/sending-sms) for error handling examples. ### Can I test the API? Yes! Use the Free plan to test the API with up to 300 messages per month. ## Troubleshooting ### My device shows as disconnected Try these steps: 1. Check your internet connection 2. Restart the textbee.dev app 3. Re-register your device 4. Check app permissions See our [reconnecting device guide](/docs/getting-started/reconnecting-an-old-device) for detailed steps. ### Messages aren't sending 1. Check that your device is connected and active 2. Verify your API key is correct 3. Check that you haven't exceeded your message limits 4. Verify phone numbers are in E.164 format (+1234567890) 5. Check the API response for error messages ### I'm not receiving SMS messages 1. Make sure SMS receiving is enabled in the app 2. Check that your device is connected 3. Verify the phone number is correct 4. Check your mobile plan's SMS capabilities ### The app won't install 1. Make sure you've enabled installation from unknown sources 2. Check that you have enough storage space 3. Try downloading the APK again 4. Ensure your device is running Android 7.0 or higher ### API requests are failing 1. Verify your API key is correct 2. Check that your Device ID is correct 3. Ensure you're using the correct API endpoint 4. Check rate limits - you may have exceeded them 5. Verify request format (JSON, headers, etc.) ## Security & Privacy ### Is my data secure? Yes! All API communications are encrypted using HTTPS/TLS. Your messages are sent directly through your Android device - no third-party SMS gateway involved. ### Where are my messages stored? Messages are temporarily stored on textbee.dev servers for delivery and retrieval. You can configure data retention settings in your dashboard. ### Can I revoke API keys? Yes, you can revoke API keys at any time from your dashboard. ### Is textbee.dev open source? Yes! The textbee.dev code is available on [GitHub](https://github.com/textbee/textbee). ## Support ### How do I get help? - Check our [documentation](/docs) - Visit our [FAQ](/docs/faq) (you're here!) - Ask the [community on Discord](https://textbee.dev/discord) - Contact support at support@textbee.dev - Check our [status page](https://status.textbee.dev) for service updates ### What's your response time? - **Free Plan**: Basic support (best effort) - **Pro Plan**: Priority support (faster response) - **Custom Plan**: Dedicated account manager ### Do you offer custom integrations? Yes! Custom integrations are available for Custom plan customers. Contact sales@textbee.dev to discuss your needs. ## Still Have Questions? Note: Can't find your answer? Ask in our [Discord community](https://textbee.dev/discord) or email support@textbee.dev. If you can't find the answer you're looking for: - Browse our [documentation](/docs) - Ask the [community on Discord](https://textbee.dev/discord) - Contact support at support@textbee.dev - Check our [status page](https://status.textbee.dev) for service updates We're here to help! # API reference Base URL: https://api.textbee.dev. Every request carries the x-api-key header. ## GET /api/v1/gateway/stats - Get account totals Source: https://textbee.dev/docs/api-reference#get-api-v1-gateway-stats Messages sent, messages received, devices, and API keys across your whole account. Response 200: Account totals. Response 200 fields: - data (GatewayStatsDTO, required): Account totals. - data.totalSentSMSCount (number, required): Messages sent across all your devices. - data.totalReceivedSMSCount (number, required): Messages received across all your devices. - data.totalDeviceCount (number, required): Devices on your account. - data.totalApiKeyCount (number, required): API keys on your account. Errors: - 401: Missing, invalid, or revoked API key. Example: ```bash curl "https://api.textbee.dev/api/v1/gateway/stats" \ -H "x-api-key: YOUR_API_KEY" ``` ## GET /api/v1/gateway/devices - List your devices Source: https://textbee.dev/docs/api-reference#get-api-v1-gateway-devices Every phone paired with your account. The push token and hardware serial are never returned. Response 200: Your devices. Response 200 fields: - data (DeviceDTO[], required): Your devices. - data[]._id (string, required): Device id. Pass it as deviceId when sending. - data[].user (string, required): Owner account id. - data[].enabled (boolean, required): Whether the device may send and receive SMS. Sending to a disabled device fails. - data[].isDefault (boolean, required): Whether sends without a deviceId go out from this device. - data[].brand (string, required): Device brand. - data[].manufacturer (string, required): Device manufacturer. - data[].model (string, required): Device model. - data[].name (string, optional): Your own label for the device. - data[].buildId (string, required): Android build id. - data[].os (string, required): Operating system name. - data[].osVersion (string, required): Android release version. - data[].osApiLevel (number, optional): Android SDK level. - data[].osVersionSource (string, optional): How osVersion was determined. One of: reported, fingerprint, buildId. - data[].osBuildFingerprint (string, optional): Android build fingerprint. - data[].appVersionName (string, optional): textbee app version name. - data[].appVersionCode (number, optional): textbee app version code. - data[].sentSMSCount (number, required): Messages this device has sent. - data[].receivedSMSCount (number, required): Messages this device has received. - data[].heartbeatEnabled (boolean, required): Whether the device reports heartbeats. - data[].heartbeatIntervalMinutes (number, required): Minutes between heartbeats. - data[].receiveSMSEnabled (boolean, required): Whether incoming messages are forwarded to textbee. Required for received message history and webhooks. - data[].smsSendDelaySeconds (number, required): Seconds the device waits between messages in a batch. - data[].lastHeartbeat (string, optional): Last heartbeat. A device silent for long is likely offline and sends will queue. - data[].batteryInfo (BatteryInfoDTO, optional): Battery level at the last heartbeat. - data[].batteryInfo.percentage (number, optional): Battery level, 0 to 100. - data[].batteryInfo.isCharging (boolean, optional): Whether the device was charging at the last heartbeat. - data[].batteryInfo.lastUpdated (string, optional): When this reading was taken. - data[].networkInfo (NetworkInfoDTO, optional): Connection the device was on at the last heartbeat. - data[].networkInfo.networkType (string, optional): Connection the device last reported. One of: wifi, cellular, none. - data[].networkInfo.lastUpdated (string, optional): When this reading was taken. - data[].appVersionInfo (AppVersionInfoDTO, optional): textbee app version running on the device. - data[].appVersionInfo.versionName (string, optional): textbee app version name. - data[].appVersionInfo.versionCode (number, optional): textbee app version code. - data[].appVersionInfo.lastUpdated (string, optional): When this reading was taken. - data[].deviceUptimeInfo (DeviceUptimeInfoDTO, optional): How long the device has been up. - data[].deviceUptimeInfo.uptimeMillis (number, optional): Milliseconds since the device booted. - data[].deviceUptimeInfo.lastUpdated (string, optional): When this reading was taken. - data[].memoryInfo (MemoryInfoDTO, optional): Memory reported at the last heartbeat. - data[].memoryInfo.freeBytes (number, optional): Free memory in bytes. - data[].memoryInfo.totalBytes (number, optional): Total memory in bytes. - data[].memoryInfo.maxBytes (number, optional): Maximum memory the app may use, in bytes. - data[].memoryInfo.lastUpdated (string, optional): When this reading was taken. - data[].storageInfo (StorageInfoDTO, optional): Storage reported at the last heartbeat. - data[].storageInfo.availableBytes (number, optional): Free storage in bytes. - data[].storageInfo.totalBytes (number, optional): Total storage in bytes. - data[].storageInfo.lastUpdated (string, optional): When this reading was taken. - data[].systemInfo (DeviceSystemInfoDTO, optional): Timezone and locale of the device. - data[].systemInfo.timezone (string, optional): Device timezone. - data[].systemInfo.locale (string, optional): Device locale. - data[].systemInfo.lastUpdated (string, optional): When this reading was taken. - data[].simInfo (SimInfoCollectionDTO, optional): SIMs installed in the device. - data[].simInfo.lastUpdated (string, required): When the device last reported its SIM list. - data[].simInfo.sims (SimInfoDTO[], required): SIMs currently installed in the device. - data[].createdAt (string, required): When the device was registered. - data[].updatedAt (string, required): When the device was last updated. Errors: - 401: Missing, invalid, or revoked API key. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#get-api-v1-gateway-devices-id Full state of one device, including its last heartbeat, battery, and SIM list. Path parameters: - id (string, required): Device id, from GET /gateway/devices. Response 200: The device. Response 200 fields: - data (DeviceDTO, required): The device. - data._id (string, required): Device id. Pass it as deviceId when sending. - data.user (string, required): Owner account id. - data.enabled (boolean, required): Whether the device may send and receive SMS. Sending to a disabled device fails. - data.isDefault (boolean, required): Whether sends without a deviceId go out from this device. - data.brand (string, required): Device brand. - data.manufacturer (string, required): Device manufacturer. - data.model (string, required): Device model. - data.name (string, optional): Your own label for the device. - data.buildId (string, required): Android build id. - data.os (string, required): Operating system name. - data.osVersion (string, required): Android release version. - data.osApiLevel (number, optional): Android SDK level. - data.osVersionSource (string, optional): How osVersion was determined. One of: reported, fingerprint, buildId. - data.osBuildFingerprint (string, optional): Android build fingerprint. - data.appVersionName (string, optional): textbee app version name. - data.appVersionCode (number, optional): textbee app version code. - data.sentSMSCount (number, required): Messages this device has sent. - data.receivedSMSCount (number, required): Messages this device has received. - data.heartbeatEnabled (boolean, required): Whether the device reports heartbeats. - data.heartbeatIntervalMinutes (number, required): Minutes between heartbeats. - data.receiveSMSEnabled (boolean, required): Whether incoming messages are forwarded to textbee. Required for received message history and webhooks. - data.smsSendDelaySeconds (number, required): Seconds the device waits between messages in a batch. - data.lastHeartbeat (string, optional): Last heartbeat. A device silent for long is likely offline and sends will queue. - data.batteryInfo (BatteryInfoDTO, optional): Battery level at the last heartbeat. - data.batteryInfo.percentage (number, optional): Battery level, 0 to 100. - data.batteryInfo.isCharging (boolean, optional): Whether the device was charging at the last heartbeat. - data.batteryInfo.lastUpdated (string, optional): When this reading was taken. - data.networkInfo (NetworkInfoDTO, optional): Connection the device was on at the last heartbeat. - data.networkInfo.networkType (string, optional): Connection the device last reported. One of: wifi, cellular, none. - data.networkInfo.lastUpdated (string, optional): When this reading was taken. - data.appVersionInfo (AppVersionInfoDTO, optional): textbee app version running on the device. - data.appVersionInfo.versionName (string, optional): textbee app version name. - data.appVersionInfo.versionCode (number, optional): textbee app version code. - data.appVersionInfo.lastUpdated (string, optional): When this reading was taken. - data.deviceUptimeInfo (DeviceUptimeInfoDTO, optional): How long the device has been up. - data.deviceUptimeInfo.uptimeMillis (number, optional): Milliseconds since the device booted. - data.deviceUptimeInfo.lastUpdated (string, optional): When this reading was taken. - data.memoryInfo (MemoryInfoDTO, optional): Memory reported at the last heartbeat. - data.memoryInfo.freeBytes (number, optional): Free memory in bytes. - data.memoryInfo.totalBytes (number, optional): Total memory in bytes. - data.memoryInfo.maxBytes (number, optional): Maximum memory the app may use, in bytes. - data.memoryInfo.lastUpdated (string, optional): When this reading was taken. - data.storageInfo (StorageInfoDTO, optional): Storage reported at the last heartbeat. - data.storageInfo.availableBytes (number, optional): Free storage in bytes. - data.storageInfo.totalBytes (number, optional): Total storage in bytes. - data.storageInfo.lastUpdated (string, optional): When this reading was taken. - data.systemInfo (DeviceSystemInfoDTO, optional): Timezone and locale of the device. - data.systemInfo.timezone (string, optional): Device timezone. - data.systemInfo.locale (string, optional): Device locale. - data.systemInfo.lastUpdated (string, optional): When this reading was taken. - data.simInfo (SimInfoCollectionDTO, optional): SIMs installed in the device. - data.simInfo.lastUpdated (string, required): When the device last reported its SIM list. - data.simInfo.sims (SimInfoDTO[], required): SIMs currently installed in the device. - data.createdAt (string, required): When the device was registered. - data.updatedAt (string, required): When the device was last updated. Errors: - 400: The device id is not a valid id. - 401: Missing, invalid, or revoked API key. - 404: No device with that id on your account. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#post-api-v1-gateway-send-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 (application/json): - message (string, required): Text of the message. Long messages are split by the carrier. - recipients (string[], required): Phone numbers to send to, in international format. Each recipient is billed as one message. - simSubscriptionId (number, optional): SIM to send from, as subscriptionId from the device simInfo. Defaults to the device default SIM. - scheduledAt (string, optional): ISO 8601 time to send the message. Must be in the future. Omit to send now. - deviceId (string, optional): Device 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: - data (SendSMSResultDTO, required): Outcome of the send. - data.success (boolean, optional): Whether the batch was accepted. Queued sends only. - data.message (string, optional): Human readable outcome. Queued sends only. - data.smsBatchId (string, optional): Batch id. Pass it to GET /gateway/devices/{id}/sms-batch/{smsBatchId} to follow delivery. Queued sends only. - data.recipientCount (number, optional): Number of recipients in the batch. Queued sends only. - data.successCount (number, optional): Messages pushed to the device. Returned instead of the queue fields when the instance dispatches immediately. - data.failureCount (number, optional): Messages that could not be pushed to the device. Errors: - 400: No enabled device to send from, the device is disabled, your email is not verified, or the message could not be pushed to the phone. - 401: Missing, invalid, or revoked API key. - 429: Your daily, monthly, or per-batch plan limit is used up. The body says which one. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#post-api-v1-gateway-send-bulk-sms 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 (application/json): - messageTemplate (string, optional): Optional label for the batch. Each entry in messages carries its own text. - messages (SMSData[], required): Messages to send. Every message can target different recipients and use a different SIM. - messages[].message (string, required): Text of the message. Long messages are split by the carrier. - messages[].recipients (string[], required): Phone numbers to send to, in international format. Each recipient is billed as one message. - messages[].simSubscriptionId (number, optional): SIM to send from, as subscriptionId from the device simInfo. Defaults to the device default SIM. - messages[].scheduledAt (string, optional): ISO 8601 time to send the message. Must be in the future. Omit to send now. - deviceId (string, optional): Device 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: - data (SendSMSResultDTO, required): Outcome of the send. - data.success (boolean, optional): Whether the batch was accepted. Queued sends only. - data.message (string, optional): Human readable outcome. Queued sends only. - data.smsBatchId (string, optional): Batch id. Pass it to GET /gateway/devices/{id}/sms-batch/{smsBatchId} to follow delivery. Queued sends only. - data.recipientCount (number, optional): Number of recipients in the batch. Queued sends only. - data.successCount (number, optional): Messages pushed to the device. Returned instead of the queue fields when the instance dispatches immediately. - data.failureCount (number, optional): Messages that could not be pushed to the device. Errors: - 400: No enabled device to send from, the device is disabled, your email is not verified, or the batch could not be pushed to the phone. - 401: Missing, invalid, or revoked API key. - 429: Your daily, monthly, or per-batch plan limit is used up. The body says which one. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#get-api-v1-gateway-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: - cursor (string, optional): Opaque position from a previous response nextCursor. Returns the page after that position and switches meta to nextCursor/hasMore without a total count. - limit (integer, optional): Messages per page. Default 50, maximum 100. Defaults to 50. Between 1 and 100. - page (integer, optional): Page to return. Default 1. Mutually exclusive with cursor. Defaults to 1. - order (string, optional): desc (default) for newest first; asc to walk forward in time when polling. One of: desc, asc. - to (string, optional): Exclusive upper bound on createdAt, same formats as from. Exclusive so consecutive windows never double-count a boundary message. - from (string, optional): Inclusive 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. - search (string, optional): Match against the message text and the other party number. Encrypted messages cannot be searched. - status (string, optional): Delivery state to return. Combine with direction: direction=sent&status=failed lists sends that failed. One of: pending, dispatched, sent, delivered, failed, unknown, received. - smsBatchId (string, optional): Only messages from this batch, using the smsBatchId returned by a send. Combine with status=failed to list the recipients of a batch that failed. - direction (string, optional): Direction 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. - deviceIds (string, optional): Comma-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: - data (MessageDTO[], required): Messages, newest first unless order=asc. - data[]._id (string, required): Message id. - data[].message (string, optional): Message text. Empty when the message is end to end encrypted. - data[].device (MessageDeviceDTO, required): Device that sent or received the message. - data[].device._id (string, required): Device id. - data[].device.enabled (boolean, required): Whether the device may send and receive SMS. - data[].device.brand (string, required): Device brand. - data[].device.model (string, required): Device model. - data[].device.buildId (string, required): Android build id. - data[].status (string, optional): Delivery 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[].sender (string, optional): Sender number. Set on received messages. - data[].recipient (string, optional): Destination number. Set on sent messages. - data[].smsBatch (string, optional): Id of the batch this message was sent in. - data[].encrypted (boolean, optional): Whether the body is end to end encrypted. Encrypted bodies can only be read by your own client. - data[].simSubscriptionId (number, optional): SIM the message was sent from. - data[].receivedAt (string, optional): When the message was received. Received messages only. - data[].requestedAt (string, optional): When the send was requested. Sent messages only. - data[].dispatchedAt (string, optional): When the send job reached the device. - data[].sentAt (string, optional): When the device reported the message as sent. - data[].deliveredAt (string, optional): When the carrier confirmed delivery. - data[].failedAt (string, optional): When the message failed. - data[].errorCode (string, optional): Failure code reported by the device. - data[].errorMessage (string, optional): Failure reason reported by the device. - data[].createdAt (string, required): When the record was created. - data[].updatedAt (string, required): When the record was last updated. - data[].direction (string, required): Direction 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[].channel (string, optional): Message channel. Currently always sms; mms will appear here when supported. Absent means sms. One of: sms. - meta (object, required): Pagination 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: - 400: Invalid deviceIds, smsBatchId, direction, status, from, to, order, or cursor value. Unknown filter values fail rather than silently applying no filter. - 401: Missing, invalid, or revoked API key. - 404: A deviceIds entry or the smsBatchId is not on your account. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#get-api-v1-gateway-devices-id-sms-smsid A single sent or received message with its delivery timestamps. Use it to check the outcome of one recipient. Path parameters: - id (string, required): Device id, from GET /gateway/devices. - smsId (string, required): Message id, from the message history response. Response 200: The message. Response 200 fields: - data (RetrieveSMSDTO, required): The message. - data._id (string, required): Message id. - data.message (string, optional): Message text. Empty when the message is end to end encrypted. - data.device (MessageDeviceDTO, required): Device that sent or received the message. - data.device._id (string, required): Device id. - data.device.enabled (boolean, required): Whether the device may send and receive SMS. - data.device.brand (string, required): Device brand. - data.device.model (string, required): Device model. - data.device.buildId (string, required): Android build id. - data.status (string, optional): Delivery 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.sender (string, optional): Sender number. Set on received messages. - data.recipient (string, optional): Destination number. Set on sent messages. - data.smsBatch (string, optional): Id of the batch this message was sent in. - data.encrypted (boolean, optional): Whether the body is end to end encrypted. Encrypted bodies can only be read by your own client. - data.simSubscriptionId (number, optional): SIM the message was sent from. - data.receivedAt (string, optional): When the message was received. Received messages only. - data.requestedAt (string, optional): When the send was requested. Sent messages only. - data.dispatchedAt (string, optional): When the send job reached the device. - data.sentAt (string, optional): When the device reported the message as sent. - data.deliveredAt (string, optional): When the carrier confirmed delivery. - data.failedAt (string, optional): When the message failed. - data.errorCode (string, optional): Failure code reported by the device. - data.errorMessage (string, optional): Failure reason reported by the device. - data.createdAt (string, required): When the record was created. - data.updatedAt (string, required): When the record was last updated. Errors: - 400: The device id is not a valid id. - 401: Missing, invalid, or revoked API key. - 404: No such message on this device. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#get-api-v1-gateway-devices-id-sms-batch-smsbatchid The batch returned by a send, plus one message per recipient. Poll this to see how a send is progressing. Path parameters: - id (string, required): Device id, from GET /gateway/devices. - smsBatchId (string, required): Batch id, returned as smsBatchId by the send endpoints. Response 200: The batch and its messages. Response 200 fields: - data (SMSBatchResultDTO, required): The batch and the messages in it. - data.batch (SMSBatchDTO, required): The batch itself. - data.batch._id (string, required): Batch id. - data.batch.user (string, required): Owner account id. - data.batch.message (string, optional): Message text sent to every recipient in the batch. - data.batch.encrypted (boolean, optional): Whether the body is end to end encrypted. - data.batch.recipientCount (number, required): Recipients in the batch. - data.batch.recipientPreview (string, optional): Short preview of the recipient list. - data.batch.successCount (number, required): Messages sent so far. - data.batch.failureCount (number, required): Messages that failed. - data.batch.status (string, optional): Progress 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.error (string, optional): Failure reason when the batch failed. - data.batch.completedAt (string, optional): When the batch finished. - data.batch.createdAt (string, required): When the batch was created. - data.batch.updatedAt (string, required): When the batch was last updated. - data.messages (RetrieveSMSDTO[], required): Every message in the batch, one per recipient. - data.messages[]._id (string, required): Message id. - data.messages[].message (string, optional): Message text. Empty when the message is end to end encrypted. - data.messages[].device (MessageDeviceDTO, required): Device that sent or received the message. - data.messages[].status (string, optional): Delivery 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[].sender (string, optional): Sender number. Set on received messages. - data.messages[].recipient (string, optional): Destination number. Set on sent messages. - data.messages[].smsBatch (string, optional): Id of the batch this message was sent in. - data.messages[].encrypted (boolean, optional): Whether the body is end to end encrypted. Encrypted bodies can only be read by your own client. - data.messages[].simSubscriptionId (number, optional): SIM the message was sent from. - data.messages[].receivedAt (string, optional): When the message was received. Received messages only. - data.messages[].requestedAt (string, optional): When the send was requested. Sent messages only. - data.messages[].dispatchedAt (string, optional): When the send job reached the device. - data.messages[].sentAt (string, optional): When the device reported the message as sent. - data.messages[].deliveredAt (string, optional): When the carrier confirmed delivery. - data.messages[].failedAt (string, optional): When the message failed. - data.messages[].errorCode (string, optional): Failure code reported by the device. - data.messages[].errorMessage (string, optional): Failure reason reported by the device. - data.messages[].createdAt (string, required): When the record was created. - data.messages[].updatedAt (string, required): When the record was last updated. Errors: - 400: The device id is not a valid id. - 401: Missing, invalid, or revoked API key. - 404: No such batch on this device. Example: ```bash curl "https://api.textbee.dev/api/v1/gateway/devices/ID/sms-batch/SMS_BATCH_ID" \ -H "x-api-key: YOUR_API_KEY" ``` ## GET /api/v1/webhooks - List your webhook subscriptions Source: https://textbee.dev/docs/api-reference#get-api-v1-webhooks 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: - data (WebhookSubscriptionDTO[], required): Your webhook subscriptions. Deleted ones are not returned. - data[]._id (string, required): Subscription id. - data[].user (string, required): Owner account id. - data[].name (string, optional): Label shown in the dashboard. - data[].isActive (boolean, required): Whether deliveries are attempted. textbee pauses subscriptions that keep failing. - data[].events (string[], required): Events this subscription receives. - data[].deliveryUrl (string, required): URL events are POSTed to. - data[].signingSecret (string, required): Secret used to sign deliveries. - data[].successfulDeliveryCount (number, required): Deliveries that succeeded. - data[].deliveryFailureCount (number, required): Deliveries that failed. - data[].deliveryAttemptCount (number, required): Delivery attempts made, retries included. - data[].lastDeliveryAttemptAt (string, optional): Last time a delivery was attempted. - data[].lastDeliverySuccessAt (string, optional): Last time a delivery succeeded. - data[].lastDeliveryFailureAt (string, optional): Last time a delivery failed. - data[].notes (WebhookNoteDTO[], optional): Notes textbee added, such as an auto-pause reason. - data[].notes[].at (string, required): When the note was added. - data[].notes[].text (string, required): What textbee recorded, for example why the subscription was paused. - data[].createdAt (string, required): When the subscription was created. - data[].updatedAt (string, required): When it was last updated. Errors: - 401: Missing, invalid, or revoked API key. Example: ```bash curl "https://api.textbee.dev/api/v1/webhooks" \ -H "x-api-key: YOUR_API_KEY" ``` ## POST /api/v1/webhooks - Create a webhook subscription Source: https://textbee.dev/docs/api-reference#post-api-v1-webhooks 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 (application/json): - name (string, optional): Label shown in the dashboard. Up to 64 characters. - deliveryUrl (string, required): URL textbee POSTs events to. Must be http or https and publicly reachable. Private and loopback hosts are rejected. - signingSecret (string, required): Shared 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. - events (string[], required): Events to deliver. At least one is required. Response 201: The subscription was created. Response 201 fields: - data (WebhookSubscriptionDTO, required): The subscription. - data._id (string, required): Subscription id. - data.user (string, required): Owner account id. - data.name (string, optional): Label shown in the dashboard. - data.isActive (boolean, required): Whether deliveries are attempted. textbee pauses subscriptions that keep failing. - data.events (string[], required): Events this subscription receives. - data.deliveryUrl (string, required): URL events are POSTed to. - data.signingSecret (string, required): Secret used to sign deliveries. - data.successfulDeliveryCount (number, required): Deliveries that succeeded. - data.deliveryFailureCount (number, required): Deliveries that failed. - data.deliveryAttemptCount (number, required): Delivery attempts made, retries included. - data.lastDeliveryAttemptAt (string, optional): Last time a delivery was attempted. - data.lastDeliverySuccessAt (string, optional): Last time a delivery succeeded. - data.lastDeliveryFailureAt (string, optional): Last time a delivery failed. - data.notes (WebhookNoteDTO[], optional): Notes textbee added, such as an auto-pause reason. - data.notes[].at (string, required): When the note was added. - data.notes[].text (string, required): What textbee recorded, for example why the subscription was paused. - data.createdAt (string, required): When the subscription was created. - data.updatedAt (string, required): When it was last updated. Errors: - 400: The 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. - 401: Missing, invalid, or revoked API key. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#get-api-v1-webhooks-notifications 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: - page (number, optional): Page to return. Default 1. - limit (number, optional): Records per page. Default 10. - status (string, optional): Only return deliveries in this state. One of: pending, retrying, delivered, failed. - eventType (string, optional): Only return deliveries for this event. One of: MESSAGE_RECEIVED, MESSAGE_SENT, MESSAGE_DELIVERED, MESSAGE_FAILED, UNKNOWN_STATE, SMS_STATUS_UPDATED. - deviceId (string, optional): Only return deliveries for messages from this device. - start (string, optional): Start of the time range, ISO 8601. Applied only together with end. - end (string, optional): End of the time range, ISO 8601. - webhookSubscriptionId (string, optional): Only return deliveries for one subscription. Response 200: A page of delivery records. Response 200 fields: - data (WebhookNotificationPageDTO, required): Delivery records with pagination. - data.data (WebhookNotificationDTO[], required): Delivery records, newest first. - data.data[]._id (string, required): Delivery record id. - data.data[].webhookSubscription (string, required): Subscription this belongs to. - data.data[].event (string, required): Event that was delivered. One of: MESSAGE_RECEIVED, MESSAGE_SENT, MESSAGE_DELIVERED, MESSAGE_FAILED, UNKNOWN_STATE, SMS_STATUS_UPDATED. - data.data[].payload (object, required): Exact JSON body textbee POSTed to your endpoint. - data.data[].computedStatus (string, required): Delivery state. Retrying means textbee will try again, failed means it gave up after 10 attempts. One of: pending, retrying, delivered, failed. - data.data[].deliveryUrl (string, optional): URL the delivery was sent to when it was attempted. - data.data[].deliveryAttemptCount (number, required): Attempts made for this event. - data.data[].deliveredAt (string, optional): When your endpoint accepted the delivery. - data.data[].lastDeliveryAttemptAt (string, optional): When the last attempt was made. - data.data[].nextDeliveryAttemptAt (string, optional): When the next retry is due. - data.data[].deliveryAttemptAbortedAt (string, optional): When textbee stopped retrying. - data.data[].errorType (string, optional): Whether the failure is worth retrying. One of: retryable, non-retryable. - data.data[].httpStatusCode (number, optional): Status code your endpoint returned on the last attempt. - data.data[].responseBody (string, optional): First 1000 characters of your endpoint response. - data.data[].idempotencyKey (string, optional): Idempotency key sent with the delivery. - data.data[].createdAt (string, required): When the event was recorded. - data.meta (PaginationMetaDTO, required): Pagination info. - data.meta.page (integer, required): Current page number - data.meta.limit (integer, required): Number of items per page - data.meta.total (integer, required): Total number of items - data.meta.totalPages (integer, required): Total number of pages Errors: - 400: deviceId or webhookSubscriptionId is not a valid id. - 401: Missing, invalid, or revoked API key. - 404: No webhook subscription with that id on your account. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#get-api-v1-webhooks-webhookid One subscription with its delivery counters. Path parameters: - webhookId (string, required): Subscription id, from GET /webhooks. Response 200: The subscription. Response 200 fields: - data (WebhookSubscriptionDTO, required): The subscription. - data._id (string, required): Subscription id. - data.user (string, required): Owner account id. - data.name (string, optional): Label shown in the dashboard. - data.isActive (boolean, required): Whether deliveries are attempted. textbee pauses subscriptions that keep failing. - data.events (string[], required): Events this subscription receives. - data.deliveryUrl (string, required): URL events are POSTed to. - data.signingSecret (string, required): Secret used to sign deliveries. - data.successfulDeliveryCount (number, required): Deliveries that succeeded. - data.deliveryFailureCount (number, required): Deliveries that failed. - data.deliveryAttemptCount (number, required): Delivery attempts made, retries included. - data.lastDeliveryAttemptAt (string, optional): Last time a delivery was attempted. - data.lastDeliverySuccessAt (string, optional): Last time a delivery succeeded. - data.lastDeliveryFailureAt (string, optional): Last time a delivery failed. - data.notes (WebhookNoteDTO[], optional): Notes textbee added, such as an auto-pause reason. - data.notes[].at (string, required): When the note was added. - data.notes[].text (string, required): What textbee recorded, for example why the subscription was paused. - data.createdAt (string, required): When the subscription was created. - data.updatedAt (string, required): When it was last updated. Errors: - 401: Missing, invalid, or revoked API key. - 404: No webhook subscription with that id on your account. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#patch-api-v1-webhooks-webhookid Changes only the fields you send. Use isActive to re-enable a subscription textbee paused after repeated failures. Path parameters: - webhookId (string, required): Subscription id, from GET /webhooks. Request body (application/json): - name (string, optional): Label shown in the dashboard. Up to 64 characters. - isActive (boolean, optional): Whether deliveries are attempted. Set it to true to re-enable a subscription textbee paused after repeated failures. - deliveryUrl (string, optional): New delivery URL. Same rules as on create: http or https, no private or loopback hosts. - signingSecret (string, optional): New signing secret, at least 20 characters. - events (string[], optional): Replacement event list. Cannot be empty. Response 200: The updated subscription. Response 200 fields: - data (WebhookSubscriptionDTO, required): The subscription. - data._id (string, required): Subscription id. - data.user (string, required): Owner account id. - data.name (string, optional): Label shown in the dashboard. - data.isActive (boolean, required): Whether deliveries are attempted. textbee pauses subscriptions that keep failing. - data.events (string[], required): Events this subscription receives. - data.deliveryUrl (string, required): URL events are POSTed to. - data.signingSecret (string, required): Secret used to sign deliveries. - data.successfulDeliveryCount (number, required): Deliveries that succeeded. - data.deliveryFailureCount (number, required): Deliveries that failed. - data.deliveryAttemptCount (number, required): Delivery attempts made, retries included. - data.lastDeliveryAttemptAt (string, optional): Last time a delivery was attempted. - data.lastDeliverySuccessAt (string, optional): Last time a delivery succeeded. - data.lastDeliveryFailureAt (string, optional): Last time a delivery failed. - data.notes (WebhookNoteDTO[], optional): Notes textbee added, such as an auto-pause reason. - data.notes[].at (string, required): When the note was added. - data.notes[].text (string, required): What textbee recorded, for example why the subscription was paused. - data.createdAt (string, required): When the subscription was created. - data.updatedAt (string, required): When it was last updated. Errors: - 400: The delivery URL is unusable, the signing secret is shorter than 20 characters, or the event list is empty or unknown. - 401: Missing, invalid, or revoked API key. - 404: No webhook subscription with that id on your account. Example: ```bash 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 Source: https://textbee.dev/docs/api-reference#delete-api-v1-webhooks-webhookid Stops all deliveries for this subscription. Its delivery history stays readable through GET /webhooks/notifications. Path parameters: - webhookId (string, required): Subscription id, from GET /webhooks. Response 200: The subscription was deleted. Response 200 fields: - data (WebhookDeletedResultDTO, required): Outcome of the delete. - data.success (boolean, required): Whether the delete succeeded. Errors: - 401: Missing, invalid, or revoked API key. - 404: No webhook subscription with that id on your account. Example: ```bash curl -X DELETE "https://api.textbee.dev/api/v1/webhooks/WEBHOOK_ID" \ -H "x-api-key: YOUR_API_KEY" ```