Resell to your customers
If your platform (a CRM, a booking system, an AI agent) wants to offer WhatsApp to its own customers, you can do it with a single Turbo Notify account: each end customer gets an extra number in your account, paired from their own phone, inside your screen. You pay Turbo Notify a fixed amount per number and charge your customers whatever you want.
How it works
| Step | Who | How |
|---|---|---|
| Add the customer’s number | Your platform | POST /v1/numbers with one alias per customer; store the id from the response |
| Pair | The customer, on their phone | Types the code or scans the QR code your screen shows |
| Send and receive | Your platform | REST API or MCP server on the number’s alias, events on your webhook |
| Bill the customer | Your platform | Your price |
| Remove | Your platform | DELETE /v1/numbers/{ref} |
What you need
- The Business plan. Extra numbers exist on the Business and Custom plans. An account holds up to 1,000 extra numbers; for more, talk to sales@turbonotify.com about the Custom plan.
- Your main number connected. An extra number can only be paired while the account’s main number is connected; without it, pairing fails with
reason: "main_number_not_connected". Connect it as in the Quickstart and watch it (number.disconnectedandnumber.revokedwithalias: "main"). - A key with the Resale template. Under API keys (opens in a new tab) , the Resale template selects
numbers:read,numbers:write,messages:send,messages:read,contacts:readandevents:read. The key stays on your platform’s server; never hand it to an end customer. See API key.
What it costs
Each extra number costs $17.90 per month, on top of the Business plan ($24.90 per month). Each extra number has the plan’s full allowance, which on Business is 50,000 messages per cycle, and shares no quota with the other numbers.
You decide how much to charge each customer. Turbo Notify takes no commission on your sale.
When you add a number mid-cycle, the account pays right away the pro-rata amount for the days left; from the next cycle on, the number is billed at the full price on the invoice. The number is only created if that charge is approved. Details in Extra number billing.
1. Add one number per customer
Every number has an id (like num_0a1b2c3d4e5f60718293a4b5c6d7e8f9) that Turbo Notify generates when you add it and that never changes, even if you rename the alias. Store the id and customer pair in your own database: the id returned when you add the number is the key. For a readable address, give each number a predictable alias, for example customer_4821:
curl -X POST https://api.turbonotify.com/v1/numbers \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+5511988887777", "alias": "customer_4821", "description": "Ana Souza Clinic" }'The response carries the number’s id as its first field.
The same example in Node, Python, Go, PHP, C# and Java is in Add extra numbers.
aliasaddresses the number in every route (/v1/numbers/customer_4821/messages). It starts with a letter and has up to 50 characters. It cannot start withnum_, a prefix reserved for ids.- The
idworks in the same place as the alias, on any route:/v1/numbers/num_0a1b2c3d4e5f60718293a4b5c6d7e8f9/messages. - To find a customer’s number again, call
GET /v1/numbers/customer_4821orGET /v1/numbers/num_0a1b2c3d4e5f60718293a4b5c6d7e8f9. Both answers are the same. - The number starts with
status: "pending".
Each creation is a real card charge, so the pace of creations per account is limited: above it, the response is 429 number_creation_rate_limited with a Retry-After header, and nothing is charged. Details in Add extra numbers.
2. Pair from the customer’s phone
The customer completes pairing alone, on your screen, without talking to you:
- Request the pairing with
POST /v1/numbers/customer_4821/pair. Without a body, the API generates the code; with{"method": "qr"}, it generates a QR code. - Call
GET /v1/numbers/customer_4821every 2 seconds. When thepairingblock is filled in, checkpairing.method. Withpairing_code, showpairing.dataas text (the code, such asZ5X7-LTYL). Withqr, showpairing.dataas an image (<img src>) and replace the image on every read, because the QR code renews. In both cases, show a countdown topairing.expires_at. - Show the customer the path on the phone. For the code: WhatsApp > Linked devices > Link a device > Link with phone number instead, then type the code. For the QR code: WhatsApp > Linked devices > Link a device, then point the camera at the image.
- Keep Generate a new code (or Generate a new QR code) always visible. A mistyped code is invalidated by WhatsApp on the spot, without telling anyone; the button calls
POST .../pairagain and the new code or QR code replaces the previous one. - Finish on the result:
status: "connected"is success;status: "failed"carries the reason inreason.
Pairing requests are limited per number and per account, so WhatsApp itself does not block new codes. On a 429 pairing_rate_limited, show the time from the Retry-After header instead of retrying. The full walkthrough, with examples, is in Pairing with the API.
Once paired, the number shows under Linked devices on the customer’s phone with your organization’s name.
What to tell the customer when it fails
reason | Message for the customer |
|---|---|
pairing_timeout | The code or the QR code was not used in time. Generate a new one and use it right away. |
paired_phone_mismatch | The code was typed, or the QR code scanned, on another WhatsApp. Use the phone of the registered number. |
phone_already_bound | This number is already in use. Contact the platform’s support. |
main_number_not_connected | We are having a temporary issue. Try again in a few minutes. (For you: reconnect the main number.) |
code_generation_failed | The code or the QR code could not be obtained just now. Try again in a moment. |
connection_lost | The connection dropped during pairing. Pair again. |
pairing_failed | Pairing could not be completed. Try again. |
Treat a reason you do not know as pairing_failed. The same reason arrives in the number.connect.failed webhook.
3. One webhook for every customer
Register a single account webhook under Webhooks (opens in a new tab) . It receives the events of every number, and each event says which number it came from:
- Every event about a number carries
number_idin the envelope, right afternumber_alias. Route each event to the right customer bynumber_id, using your table ofidand customer. number.*events (connected, disconnected, revoked, pairing failure, removal) carry the sameidindata.id.- An event’s
number_aliasis the alias the number had when the event happened. If you rename a number, an older event still shows the old alias, and an old alias no longer exists in the routes. So always match onnumber_id, which does not change: the alias is for reading only.
To watch your customer base, GET /v1/numbers?status=failed or ?status=disconnected lists the numbers that need attention. When a number is revoked on the phone (number.revoked), tell the customer and offer to pair again.
4. Send and receive on the customer’s behalf
Every message, contact and group route sits under the number’s alias: POST /v1/numbers/customer_4821/messages. Through the MCP server, tools take number_alias. Quotas belong to each number, so one customer’s usage never consumes another’s allowance.
5. Remove when the customer leaves
Remove the number: DELETE /v1/numbers/customer_4821. Disconnecting it beforehand is not required.
If you remove a number right after adding it, before using it, the creation charge may be refunded automatically. Otherwise the removal is scheduled for the end of the period already paid: until then the number keeps working, and the removal can be canceled with POST /v1/numbers/{ref}/cancel-deletion. It is not included in the next period’s invoice. The DELETE response tells you what happened (refund_eligible, refund_amount_cents, refund_status, scheduled_deletion_at). Refund questions: billing@turbonotify.com. See Remove.
After the removal, the number’s entry can stay in the customer’s Linked devices list as Disconnected, using one of WhatsApp’s 4 device slots. Tell the customer that to free the slot they open that list, tap the entry and choose Remove device.
Good practices for your customers
Every number follows the plan’s sending pace, which helps protect it, and new numbers have their volume limited in the first days. WhatsApp decides on restrictions, so advise your customers to:
- Message only people who know the number and agreed to receive messages.
- Start slowly with a new number.
- Avoid sending the same message to many recipients in a row.
Before connecting a customer’s number, tell them that Turbo Notify is an independent service, not affiliated with Meta, and that WhatsApp can restrict numbers. The Terms of service (opens in a new tab) ask you to give that notice. The full practices are in Protect your number.
Next steps
- Pairing with the API: recommended screen, attempt limits and cancellation.
- Webhook: every
number.*event and the reasons behind each drop. - List numbers: the
statusfilter and each number’sid. - Extra number billing: pro-rata charge, renewal and removal.