Sendblue is one of the few platforms that supports iMessage delivery via API, and if you are reading this, you have probably hit one of its limits. The most common reason teams migrate from Sendblue to senderZ is the daily sending cap — Sendblue restricts new contacts to roughly 50 per day across all plans, with no way to increase that limit. senderZ’s Scale plan supports up to 500 new contacts per day (10,000 per month), and all plans include unlimited messages to existing contacts.
Why Teams Leave Sendblue
The 50/Day Cap
Sendblue enforces a hard daily limit on new contacts that applies regardless of your plan. For teams doing outreach, onboarding campaigns, or OTP verification at any meaningful scale, this cap becomes a blocker within the first week. senderZ gives you 10 new contacts/day on Starter, 50/day on Growth, and 500/day on Scale — and messages to contacts you have already reached are always unlimited on every plan.
No Multi-Tenant Support
If you are building a platform, agency, or SaaS that needs to send messages on behalf of multiple customers, Sendblue has no native multi-tenant model. You end up managing multiple Sendblue accounts manually. senderZ has multi-tenant isolation built into the core — each tenant gets their own API keys, contacts, opt-out lists, and phone assignments, all managed through a single operator dashboard.
Limited Compliance Tooling
Sendblue handles basic STOP keyword processing but does not offer consent logging, quiet hours enforcement, or opt-out list export. senderZ includes a full compliance suite: automatic STOP/START processing, quiet hours for marketing messages (8 PM - 8 AM local time), a Consent API for TCPA audit trails, and CSV export of all compliance data.
No MCP Server or SDK
senderZ ships an official MCP server (@senderz/mcp) for Claude Code integration and a TypeScript SDK (@senderz/sdk). Sendblue offers neither, which means more boilerplate code on your end for every integration.
Endpoint Comparison
Send a Message
curl -X POST https://api.sendblue.co/api/send-message \
-H "sb-api-key-id: YOUR_KEY_ID" \
-H "sb-api-secret-key: YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{
"number": "+15551234567",
"content": "Hello from Sendblue"
}' curl -X POST https://api.senderz.com/v1/messages \
-H "Authorization: Bearer sz_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+15551234567",
"channel": "auto",
"body": "Hello from senderZ"
}' Key differences:
- Auth: Sendblue uses two headers (
sb-api-key-id+sb-api-secret-key). senderZ uses a single Bearer token. - Field names: Sendblue uses
numberandcontent. senderZ usestoandbody. - Channel control: Sendblue auto-selects iMessage or SMS. senderZ lets you choose explicitly (
imessage,sms) or useautofor the same behavior. - Templates: Sendblue does not support message templates. senderZ has a full template system with
{{variable}}syntax for OTP codes, alerts, and marketing messages.
Check Message Status
| Sendblue | senderZ | |
|---|---|---|
| Endpoint | GET /api/send-message/status/{id} | GET /v1/messages/{message_id} |
| Response | status, error_message | status, channel, delivered_at, read_at |
senderZ provides richer status data including which channel was used (iMessage vs SMS), delivery timestamp, and read receipt timestamp for iMessage messages.
Webhooks
| Sendblue | senderZ | |
|---|---|---|
| Registration | Dashboard-only configuration | POST /v1/webhooks (API) + portal UI |
| Signature | None | HMAC-SHA256 (X-Senderz-Signature) |
| Events | Message status updates | message.sent, message.delivered, message.failed, message.received |
senderZ webhook payloads are signed with HMAC-SHA256, which Sendblue does not offer. This prevents spoofed webhook calls from reaching your handler.
Data Migration
Contacts
Export your contacts from your own database or CRM (Sendblue does not have a contacts API). Import them into senderZ using POST /v1/contacts for each contact, or use the CSV import feature in the developer portal.
Opt-Outs
If you have tracked opt-outs from your Sendblue integration, import those numbers into senderZ. Any number that opted out on Sendblue must remain opted out on senderZ. senderZ’s router will automatically block sends to imported opt-out numbers.
Consent Records
If you have consent documentation (timestamps, sources, consent types), log them into senderZ via POST /v1/compliance/consent. This establishes your audit trail on the new platform from day one. See Consent Management for details.
Feature Comparison
| Feature | Sendblue | senderZ |
|---|---|---|
| iMessage delivery | Yes | Yes |
| SMS fallback | Yes | Yes |
| New contacts/day (max plan) | ~50 | 500 (Scale) |
| Messages to existing contacts | Limited | Unlimited |
| Multi-tenant / sub-accounts | No | Yes |
| Message templates | No | Yes ({{variable}} syntax) |
| Consent logging API | No | Yes |
| Quiet hours enforcement | No | Yes (automatic) |
| Opt-out list export | No | Yes (CSV) |
| MCP server (Claude Code) | No | Yes (@senderz/mcp) |
| TypeScript SDK | No | Yes (@senderz/sdk) |
| Webhook signatures | No | HMAC-SHA256 |
| Team members | No | Up to 10 (Scale) |
| Dedicated phone numbers | Varies | Up to 3 (Scale) |
| iMessage detection API | No | Yes (GET /v1/capabilities/:number) |
| Campaign scheduling | No | Yes |
Migration Timeline
Most teams migrating from Sendblue complete the switch in 1-3 days because the API surface is smaller than Twilio’s.
| Day | Activity |
|---|---|
| Day 1 | Sign up, get API key, update endpoint URLs and auth headers, send test messages |
| Day 2 | Import contacts, opt-outs, and consent records. Register webhooks. |
| Day 3 | Route production traffic to senderZ, verify delivery, deactivate Sendblue |
SDK Quick Start
If you were calling Sendblue’s API directly with fetch, you can optionally switch to the senderZ TypeScript SDK for a cleaner integration:
import { SenderZ } from '@senderz/sdk'
const sz = new SenderZ({ apiKey: 'sz_live_YOUR_KEY' })
// Send a message
const msg = await sz.messages.send({
to: '+15551234567',
channel: 'auto',
body: 'Welcome to our platform!',
})
// Check status
const status = await sz.messages.get(msg.id)
console.log(status.channel) // "imessage" or "sms"
See the SDK Reference for the full method list.