Skip to content

Webhooks overview

Lisoloo delivers status updates asynchronously to a URL you configure on your API key. Each event is a single HTTP POST with a JSON body and the optional HTTP Basic credentials you set.

For any send of more than a handful of recipients, polling GET /status/{message_id} is the wrong tool — it burns your 120 reads/minute rate-limit and adds latency. Webhooks push the final state directly to your server, in real time, for free (no extra rate-limit cost on your end).

┌──────────────┐ webhook POST ┌────────────────┐
POST /send ─▶ │ Lisoloo API │ ──────────────▶ │ Your endpoint │
└──────────────┘ on each event └────────────────┘
└─ status transitions internally:
pending → processing → sent → delivered
  • HTTP method: POST.
  • Content-Type: application/json.
  • Body: a single event object (see Event types).
  • Authentication: HTTP Basic with the credentials configured on your API key, if set. No HMAC signature today.
  • Retries: up to 4 attempts on 5xx responses or connection failures, with exponential backoff 30s → 2m → 10m → 1h. After 4 failures the event is dropped.
  • Order: not guaranteed. A sms.delivered event for one recipient may arrive before the sms.sent event for another in the same batch. Use recipient_phone to correlate; rely on the authoritative state in GET /status if order matters.
  • Idempotency: every event has an event_id (UUID v4). Your endpoint must be idempotent — replay with the same event_id must be a no-op.

Webhook configuration lives on the API key, not the merchant account. You configure it in the dev portal:

  1. Open Bloonio → Lisoloo → Developer → API keys.
  2. Scroll to Webhook configuration.
  3. Set webhook_url to an HTTPS endpoint on your server.
  4. (Optional but recommended) set webhook_basic_auth_username and webhook_basic_auth_password. The gateway will use these for HTTP Basic auth on every POST.
  5. Save.

The full walkthrough — including the write-only password field and the “Basic auth configured” indicator — is at Webhooks → Configuration.

Every event has the same outer envelope:

{
"event_id": "f8a3b7c1-2e4d-4a9b-9d8f-7c6e5b4a3d2c",
"event_type": "sms.delivered",
"timestamp": "2026-05-27T10:15:08Z",
"message_id": "507f1f77bcf86cd799439011",
"data": {
...event-specific payload...
}
}

The event_type values and per-event data shapes are documented at Webhook event types.

A 2xx status (200, 201, or 204) acknowledges the event. The body is ignored. Any 4xx is treated as a permanent failure (the event will not retry — typically used to refuse misrouted events). Any 5xx or connection error triggers the retry sequence.

HTTP/1.1 204 No Content

Aim to respond in under 5 seconds. Acks beyond 5 seconds are treated as timeout and trigger a retry. If your handling is slow, accept first and process async — push the event into a queue and return 204 immediately.

webhook.site and smee.io both expose a public URL that forwards to your laptop. Useful for early integration; for production routing use your own domain with TLS.

For unit tests, the sandbox webhook_url accepts any HTTPS URL — fire a sandbox POST /send against a webhook.site URL and watch the events arrive within a few seconds.