If you are adding iMessage to a product other people pay for, you are not really buying a messaging API. You are taking on a dependency, a compliance surface and a pricing mismatch all at once, and each deserves a decision before you write code.
The pricing mismatch, first
This is the one that catches teams out after launch. iMessage providers bill per line, per month. SaaS bills per seat or per plan. Those two shapes do not compose without a deliberate decision.
The trap
- Bundle messaging into an existing plan
- Every customer who enables it costs you a line
- A $39–$250 monthly cost lands against a $29 plan
- Your best-margin customers subsidise the messaging ones
What works
- Make a line an explicit billable unit
- Charge a messaging add-on that covers the line plus margin
- Or pool a shared line and cap volume per tenant
- Either way, cost scales with the thing that actually costs you
Shared lines are cheaper and riskier
Pooling one line across tenants collapses the cost problem, but one careless customer's sending behaviour degrades deliverability for everyone on that number — and one opt-out complaint can affect all of them. If you pool, you must police volume and content yourself.
Consent belongs to your customer, not you
This is the compliance point that matters most and gets thought about least. When your SaaS sends a message on a customer's behalf, your customer holds the relationship with the recipient — and therefore the consent obligation. You are the processor.
That has concrete product consequences you have to build, not just document.
- Store consent per tenant, per recipient, with a timestamp and a source. If a customer cannot show when someone opted in, neither can you.
- Enforce opt-out globally and immediately. A STOP reply must suppress that number for that tenant across every code path, including any queue already holding messages for them.
- Do not let one tenant import another's list. Obvious, and worth a constraint in the schema rather than a line in the docs.
- Put the sending business's identity in the message. The recipient consented to hear from your customer, not from you.
- Give tenants an export. Their consent records are their compliance artefact, not yours to hold hostage.
The underlying rules are in consent before you text and compliance.
Architecture for multi-tenant sending
The shape that holds up: a single messaging service that every tenant's sends flow through, with suppression and rate limiting enforced centrally rather than by each feature that happens to send something.
type Outbound = { tenantId: string; to: string; text: string; campaign: string;}; export async function dispatch(msg: Outbound) { // 1. Consent, per tenant. Checked here so no feature can skip it. if (!(await hasConsent(msg.tenantId, msg.to))) { throw new NoConsentError(msg.tenantId, msg.to); } // 2. Suppression beats everything, including a scheduled campaign. if (await isSuppressed(msg.tenantId, msg.to)) return { skipped: "suppressed" }; // 3. Quiet hours in the RECIPIENT's timezone, not your server's. if (await inQuietHours(msg.to)) return await enqueueForMorning(msg); // 4. Per-tenant rate limit, so one customer cannot burn a shared line. await rateLimiter.consume(msg.tenantId); const line = await lineFor(msg.tenantId); const result = await provider.send({ from: line, to: msg.to, text: msg.text }); // 5. Record what actually happened, per tenant, for their reporting. await recordSend({ ...msg, messageId: result.id, channel: result.channel }); return result;}Everything in that function is a rule you would otherwise have to remember in every feature that sends a message. Centralising it is the difference between a compliance property and a compliance hope.
Choosing a provider as a SaaS
Your priorities differ from a single business's. Weight these heavily.
| Criterion | Why it matters more for SaaS | What to ask |
|---|---|---|
| Multi-tenancy | You need many lines under one account with clean separation | Can I provision and release lines programmatically? |
| Line provisioning API | Manual line setup does not scale past your first few customers | Is there an API, or is it a support ticket? |
| Reseller terms | Some vendors restrict sending on behalf of third parties | Get it in writing before you build |
| Webhook reliability | Your customers see your product fail, not the vendor's | Retry policy, ordering guarantees, delivery events |
| Portability | Vendor risk is your product risk now | How are numbers released if we leave? |
| SOC 2 | Your enterprise customers will ask you, and you will ask the vendor | Only one vendor currently claims it |
Tell your customers what the channel is
Blue-bubble delivery is unofficial and can be disrupted. If you sell it as a feature without saying so, an outage becomes a trust problem rather than a status page entry. Describing it accurately — 'iMessage where available, SMS fallback always' — costs nothing and protects you.
The vendor risk framing is in iMessage vendor risk; the switching mechanics are in switching providers.
Common questions
- Can I resell iMessage messaging inside my SaaS product?
- Technically yes, and several vendors support multi-tenant use. Commercially, check your provider's terms on reselling, and be careful about who owns consent — usually your customer, not you.
- How should SaaS products price iMessage messaging?
- Providers charge per line per month, so the cleanest model is to make a line a billable unit of your own product rather than trying to recover a fixed monthly cost through per-message pricing.