# SMS, email and failover

Send by SMS and email next to WhatsApp, and let a notification fall back from one channel to the next.

> **In a nutshell:** Set up SMS (Arkesel by default, or Hubtel, under a sender ID - optionally with the business's own Arkesel key) or email (Resend, from an address on a verified domain) per business, then send with channel sms or email. A notification tries its channels in order - WhatsApp, then SMS, then email - and moves on when a channel cannot be used or its message fails.

## SMS and email

PaalTech's SMS and Resend accounts send for every business, so there is nothing to connect:

- **SMS** - [Set up SMS or email](/docs/api/enable-channel) with a `sender_id` and, if you
  like, a `provider`: `arkesel` (the default) or `hubtel`. Each business uses one; call again
  to switch. A business's own sender ID must first be approved by that provider. Arkesel
  reports delivery back to PaalChat; Hubtel's delivery is checked for two days after sending.
- **SMS with the business's own Arkesel account** - pass its key as `arkesel.api_key`.
  PaalChat checks it with Arkesel (`invalid_provider_credentials` if Arkesel refuses it),
  stores it encrypted and never returns it - the connection shows `own_key: true`. The
  business then pays Arkesel itself. Send `"arkesel": {"api_key": null}` to go back to
  PaalTech's account.
- **Email** - set it up with a `from` address on a domain PaalChat sends for, and optionally
  `from_name` and `reply_to`. Delivery, bounces and spam complaints come back from Resend;
  bounced and complaining addresses go on the business's suppression list.

```json
{"provider": "arkesel", "sender_id": "PRESEC", "arkesel": {"api_key": "the-school's-arkesel-key"}}
```

Then send with [Send message](/docs/api/send-message) and `channel`:

```json
{"channel": "sms", "to": "+233241234567", "type": "text", "reference": "closing-sms-1",
 "text": {"body": "Presec: school closes at 1pm today."}}
```

```json
{"channel": "email", "to": "parent@example.com", "type": "text", "subject": "Report cards",
 "text": {"body": "Report cards are ready at the school office."}}
```

SMS and email are always business-initiated, so the suppression list, consent, preferences
and quiet hours apply, like WhatsApp templates. `message.status` callbacks carry `channel`.

## Notifications with failover

[Send notification](/docs/api/send-notification) sends one notification on the first channel
that takes it:

```json
{"contact_id": 41, "reference": "closing-2026-10-02",
 "channels": ["whatsapp", "sms", "email"],
 "whatsapp": {"template": {"name": "school_closing", "language": "en_US"}},
 "sms": {"text": "Presec: school closes at 1pm today."},
 "email": {"subject": "School closes early", "text": "School closes at 1pm today."}}
```

A channel is passed over when there is no content or address for it, the business has not
set it up, its provider is unavailable, or the send is refused. If the message then fails -
for example the number is not on WhatsApp - the next channel is tried. A message whose fate
is unknown (the provider's answer was lost) never moves on, because it may already have
arrived. [`notification.updated`](/docs/api/callbacks/notification-updated) says how it
ended, and [Get notification](/docs/api/get-notification) lists every attempt.

## Provider health

[Get provider health](/docs/api/get-providers) says whether Meta, Arkesel, Hubtel and Resend work right
now; the [status page](/status) shows the same.
