Delivery reportsAvailable

Receive every SMS status change in real time.

Sendimo POSTs an event to your URL each time a message changes status, so you don't need to poll. Set the URL and copy the signing secret (whsec_…) in the dashboard.

Events

EventWhen
message.sentHanded to the operator
message.deliveredDelivery confirmed
message.undeliveredOperator could not deliver
message.failedRejected before sending
batch.completedEvery message in a batch reached a final status
balance.lowBalance dropped under your threshold
Request sent to your serverHTTP
POST /your/webhook HTTP/1.1
Content-Type: application/json
Sendimo-Signature: t=1761815700,v1=5f8a2b...

{
  "id": "evt_01HF9B2X",
  "type": "message.delivered",
  "created_at": "2026-10-30T09:15:04Z",
  "data": {
    "id": "msg_01HF8Z3K9QX2",
    "status": "delivered",
    "to": "+21620123456",
    "reference": "order-4821",
    "delivered_at": "2026-10-30T09:15:03Z"
  }
}

Verifying the signature

Each request carries a Sendimo-Signature: t=…,v1=… header. Compute HMAC-SHA256 of {t}.{raw body} with your signing secret and compare it to v1. Reject events where t is older than 5 minutes.

Verify the signature (Node.js)JavaScript
import crypto from "crypto";

export function verifySendimo(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return !!v1 && v1.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}
Verify the signature (Python)Python
import hashlib
import hmac
import time

def verify_sendimo(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t, v1 = parts.get("t"), parts.get("v1")
    if not t or not v1 or abs(time.time() - int(t)) > 300:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, v1)

Delivery rules

  • Respond 2xx within 10 seconds.
  • Otherwise Sendimo retries 6 times over ~24 hours: 1 min, 5 min, 30 min, 2 h, 6 h, 15 h.
  • Events can arrive more than once or out of order: dedupe on id and trust the status with the latest created_at.

Other integrations

Ready to send your SMS?

Launching soon in Tunisia. Join early access.