Developers

The SMS API you'll actually enjoy.

Everything you need to add OTPs, notifications and campaigns to your product — with the safety rails production systems deserve.

Predictable REST

JSON everywhere, consistent error codes and idempotent references.

Bulk in one call

Queue 100,000 personalised messages and poll progress by campaign.

Free test keys

jms_test_ keys exercise the whole flow without charges or deliveries.

Scoped keys

Limit each key to the actions it needs, restrict IPs and set rate limits.

Signed webhooks

Delivery reports, inbound replies and payments pushed to your server.

Safe retries

Uncertain carrier outcomes are held and reconciled — never duplicated.

Send an OTP (Node.js)
const res = await fetch("https://jmsurfsms.co.ke/api/v1/sms/send", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.JMSURF_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    to: "0712345678",
    message: `Your verification code is ${code}`,
    reference: crypto.randomUUID(),
  }),
});
Receive a delivery report (Express)
app.post("/jmsurf/webhooks", express.raw({ type: "*/*" }), (req, res) => {
  if (!verify(req.body, req.get("x-jmsurf-signature"), SECRET)) return res.sendStatus(401);
  const event = JSON.parse(req.body);
  if (event.event === "sms.delivered") markDelivered(event.data.reference);
  res.sendStatus(200);
});

Make every message count.

Start with a free workspace. Add your audience, top up with M-Pesa and keep your customers in the conversation.

Create your workspace