Number Pools
How sender number selection works for Blooio and Twilio messages
A number pool is a collection of phone numbers assigned to your API key. When you send a message, Blooio selects a sender number from this pool—either automatically or based on your specification.
How number pools work
Each API key in Blooio has its own number pool. The pool determines which phone numbers can be used as the sender (from_number) when sending messages through that API key.
┌─────────────────────────────────────────────┐
│ Your Organization │
├─────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ API Key A │ │ API Key B │ │
│ │ (iMessage) │ │ (Twilio) │ │
│ ├─────────────────┤ ├─────────────────┤ │
│ │ +1 555-111-0001 │ │ +1 555-222-0001 │ │
│ │ +1 555-111-0002 │ │ +1 555-222-0002 │ │
│ │ +1 555-111-0003 │ │ +1 555-222-0003 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────┘Each API key can only be assigned either Blooio (iMessage) numbers or Twilio numbers—never both. This ensures clear separation between messaging protocols.
Blooio (iMessage) number pools
Automatic rotation
For Blooio API keys, number selection is fully automatic with intelligent rotation:
- New conversations: Blooio selects an available number from your pool
- Ongoing conversations: The same number is used to maintain consistency
- Load distribution: Numbers rotate to distribute traffic evenly
# from_number is optional for Blooio - auto-selected from pool
curl -X POST 'https://backend.blooio.com/v2/api/chats/%2B15551234567/messages' \
-H 'Authorization: Bearer YOUR_BLOOIO_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"text": "Hello!"}'Conversation stickiness
Blooio remembers which number was used for each contact. When you message someone again, Blooio automatically uses the same sender number—no tracking required on your end.
This creates a natural experience where contacts always see messages from the same number, as if they're texting a consistent person.
Explicit number selection
You can override automatic selection by specifying from_number:
curl -X POST 'https://backend.blooio.com/v2/api/chats/%2B15551234567/messages' \
-H 'Authorization: Bearer YOUR_BLOOIO_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"text": "Hello!",
"from_number": "+15551110002"
}'The specified from_number must be in your API key's pool. Attempting to use a number from a different API key results in a 403 Forbidden error.
Allocation pools
In the Blooio dashboard, you can configure allocation pools to control how numbers are distributed:
- Round-robin: Cycle through numbers evenly
- Weighted: Assign higher volume to specific numbers
- Geographic: Match sender area codes to recipient regions
These settings are configured per-organization in the dashboard.
Twilio number pools
Manual or first-available selection
Twilio number pools work differently. When you omit from_number:
- Blooio selects the first number in your API key's Twilio pool
- No automatic rotation or conversation tracking occurs
# from_number omitted - uses first assigned Twilio number
curl -X POST 'https://backend.blooio.com/v2/api/chats/%2B15551234567/messages' \
-H 'Authorization: Bearer YOUR_TWILIO_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"text": "Hello via SMS!"}'No automatic stickiness
Unlike Blooio, Twilio pools don't maintain conversation stickiness. If you need the same number for ongoing conversations, track it yourself:
// Store which Twilio number was used for each contact
const fromNumbers = new Map()
async function sendTwilioMessage(to, text) {
// Check if we've messaged this contact before
let fromNumber = fromNumbers.get(to)
if (!fromNumber) {
// First message - let Blooio auto-select, then store it
const res = await sendMessage(to, { text })
fromNumber = res.from_number // Returned in response
fromNumbers.set(to, fromNumber)
return res
}
// Subsequent messages - use same number
return sendMessage(to, { text, from_number: fromNumber })
}Explicit selection recommended
For Twilio, explicitly specifying from_number is recommended for production:
curl -X POST 'https://backend.blooio.com/v2/api/chats/%2B15551234567/messages' \
-H 'Authorization: Bearer YOUR_TWILIO_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"text": "Hello via SMS!",
"from_number": "+15552220001"
}'Comparison: Blooio vs Twilio pools
| Feature | Blooio (iMessage) | Twilio (SMS) |
|---|---|---|
| Auto-selection | Intelligent rotation | First available |
| Conversation stickiness | Automatic | Manual tracking required |
| Pool configuration | Dashboard allocation pools | Assign numbers to API key |
| Protocol | iMessage | SMS/MMS |
| Multi-protocol support | No (iMessage only) | No (Twilio only per key) |
Setting up your number pool
For Blooio numbers
- Go to Numbers in the dashboard
- Your Blooio-registered numbers appear automatically
- Create an API key and assign numbers to it
- Configure allocation preferences in Settings
For Twilio numbers
- Go to Integrations → Twilio → Connect
- Enter your Twilio Account SID, API Key SID, and API Key Secret
- Select which Twilio numbers to import
- Create a new API key (separate from your Blooio key)
- Assign imported Twilio numbers to the API key
See Twilio Integration for detailed setup instructions.
Best practices
1. Separate API keys by use case
Create distinct API keys for different purposes:
┌─────────────────────────────────────────────┐
│ API Key: "Sales Team" → Pool: 5 numbers │
│ API Key: "Support Team" → Pool: 3 numbers │
│ API Key: "Marketing SMS" → Pool: 10 Twilio │
└─────────────────────────────────────────────┘2. Don't mix protocols in logic
Keep Blooio (iMessage) and Twilio (SMS) flows separate in your application. Different keys, different pools, different behavior.
3. Monitor number health
Numbers can become flagged by carriers. Monitor delivery rates per number and rotate out underperforming numbers.
4. Use geographic matching when possible
For Twilio pools, consider matching sender area codes to recipient regions:
function selectFromNumber(recipientNumber, twilioPool) {
const recipientAreaCode = recipientNumber.slice(2, 5)
// Find a number with matching area code
const match = twilioPool.find(n => n.slice(2, 5) === recipientAreaCode)
return match || twilioPool[0] // Fall back to first number
}5. Plan for growth
If you anticipate high volume, provision more numbers early. Adding numbers to a pool is easy; dealing with deliverability issues from over-used numbers is not.
Common errors
"This API key does not own the specified from_number"
The from_number you specified isn't assigned to your API key's pool.
Fix: Either remove from_number to use auto-selection, or assign the number to your API key in the dashboard.
"No numbers assigned to this API key"
Your API key has an empty pool.
Fix: Go to the Numbers page and assign at least one number to your API key.
"API key already owns Blooio numbers"
You tried to assign Twilio numbers to an API key that already has Blooio numbers.
Fix: Create a separate API key for Twilio numbers. Each key can only hold one protocol type.