Send SMS from your Supabase project through Nimba SMS β the West African leader in business mobile communication.
This repository ships a production-ready set of Supabase Edge Functions, SQL migrations and end-to-end examples for connecting Nimba SMS to Supabase Auth, Database triggers, and your front-end.
- π Edge Functions for every Nimba endpoint β
send-sms,sms-webhook,check-balance,get-sendernames,list-messages,list-contacts,create-contact,send-otp,confirm-otp,verify-otp - π Two OTP flows out of the box β Nimba's managed verifications (
send-otp/confirm-otp) and a custom hash-and-store flow (verify-otp) - π¦ Typed Deno client β
NimbaSMSClientwith timeouts, Basic auth, strict array payloads, typed errors - ποΈ Audit trail in Postgres β one row per recipient in
sms_logs, grouped bybatch_id, status updated by Nimba's delivery-report webhook - π Row Level Security β users only see their own SMS history
- π¬π³ Smart phone formatting β auto-prefixes Guinean numbers with
224 - π§© Ready-to-fork examples β phone OTP sign-in (HTML + JS) and order confirmation via Postgres trigger
- π‘οΈ Webhook signature verification β shared-secret authentication for inbound delivery reports
| Requirement | Where |
|---|---|
| Nimba SMS account | www.nimbasms.com |
ACCOUNT_SID + AUTH_TOKEN(labelled SERVICE_ID and SECRET_TOKEN on the Nimba dashboard) |
Nimba dashboard β API KEYS |
| Approved Sender ID | Nimba dashboard β Sender Names |
| Supabase project | supabase.com |
| Supabase CLI β₯ 1.200 | npm install -g supabase |
# 1. Clone & link to your Supabase project
git clone https://github.com/nimbasms/nimbasms-supabase
cd nimbasms-supabase
supabase link --project-ref <your-project-ref>
# 2. Configure secrets
supabase secrets set \
NIMBA_ACCOUNT_SID=your_account_sid \
NIMBA_AUTH_TOKEN=your_auth_token \
NIMBA_DEFAULT_SENDER=YourBrand \
NIMBA_WEBHOOK_SECRET="$(openssl rand -hex 32)"
# 3. Push migrations
supabase db push
# 4. Deploy functions
supabase functions deploy \
send-sms sms-webhook check-balance \
get-sendernames list-messages list-contacts create-contact \
send-otp confirm-otp verify-otp
# 5. Send a test
curl -X POST "https://<project-ref>.supabase.co/functions/v1/send-sms" \
-H "Authorization: Bearer $SUPABASE_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["224623273737", "224621000000"],
"sender_name": "MyApp",
"message": "Hello from Supabase + Nimba SMS"
}'Detailed walkthrough β docs/QUICKSTART.md.
The Nimba REST API exposes a single sending endpoint, POST /v1/messages, that
accepts a to array of 1..50 recipients in every call. This repo mirrors
that contract exactly:
- One Edge Function β
send-smsβ handles both single-recipient sends and batches; there is no separate "campaign" endpoint to learn. tois an array of bare-digit phone numbers with country code (e.g."224623273737"). A leading+is stripped. Local Guinean numbers (8β9 digits) automatically get the224prefix prepended.- Max 50 recipients per call. Split your audience client-side and call the function multiple times for larger broadcasts.
curl -X POST "$SUPABASE_URL/functions/v1/send-sms" \
-H "Authorization: Bearer $SUPABASE_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["224623273737", "224621000000"],
"sender_name": "MyApp",
"message": "Hello from Supabase + Nimba SMS"
}'import { createClient } from "@supabase/supabase-js";
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
await supabase.functions.invoke("send-sms", {
body: {
to: ["224620000000"],
sender_name: "MyApp",
message: "Your order has been confirmed.",
},
});await supabase.functions.invoke("send-sms", {
body: {
to: ["224620000000", "224621000000", "224622000000"],
sender_name: "MyShop",
message: "Don't miss our weekend offer!",
},
});For audiences >50, split client-side and call again:
for (const chunk of chunkArray(allRecipients, 50)) {
await supabase.functions.invoke("send-sms", {
body: { to: chunk, sender_name: "MyShop", message: "..." },
});
}const { data } = await supabase
.from("sms_logs")
.select("recipient, status, created_at, batch_id")
.order("created_at", { ascending: false })
.limit(20);- π± Phone OTP sign-in β custom OTP flow on top of Supabase Auth β see
examples/phone-otp-authanddocs/AUTH_OTP_GUIDE.md - π§Ύ Transactional notifications β order confirmations, shipping updates, password resets β see
examples/order-confirmation-trigger - π£ Marketing broadcasts β pass any number of recipients to
send-sms(chunk to 50 client-side) - π¨ Internal alerts β wire
pg_nettosend-smsfrom any Postgres trigger to notify ops on critical events
supabase/
ββ config.toml
ββ functions/
β ββ _shared/ β NimbaSMSClient, CORS, types
β ββ send-sms/ POST /v1/messages
β ββ sms-webhook/ β inbound delivery reports
β ββ check-balance/ GET /v1/accounts
β ββ get-sendernames/ GET /v1/sendernames
β ββ list-messages/ GET /v1/messages
β ββ list-contacts/ GET /v1/contacts
β ββ create-contact/ POST /v1/contacts
β ββ send-otp/ POST /v1/verifications (managed OTP)
β ββ confirm-otp/ PATCH /v1/verifications/{id} (managed OTP)
β ββ verify-otp/ β custom OTP flow (hash + store)
ββ migrations/ β sms_logs table + RLS policies
examples/
ββ phone-otp-auth/ β static HTML + JS demo
ββ order-confirmation-trigger/ β pg_net + Postgres trigger
docs/
ββ QUICKSTART.md
ββ API_REFERENCE.md
ββ AUTH_OTP_GUIDE.md
- Helper hook for Supabase Auth Phone provider once the platform supports custom SMS providers
- Pre-built React / Vue / Svelte components for the OTP UI
-
groupsEdge Function (GET /v1/groups) for contact-group management - Optional
pg_cronjob to backfilldelivered_atby pollingGET /messages/{id}
Open an issue if you'd like to drive any of these.
Pull requests are welcome! Please:
- Open an issue first for non-trivial changes so we can align on scope.
- Keep Edge Functions free of heavy dependencies β prefer the Deno standard
library and small
esm.sh-hosted packages with pinned versions. - Format code with
deno fmtand rundeno checkon every file.
MIT Β© Nimba SMS. See LICENSE.
- π Website β nimbasms.com
- π API docs β developers.nimbasms.com
- βοΈ Contact β contact@nimbasms.com
- π Bugs / feature requests β GitHub Issues