Skip to content
OmniChannels.ai

Messaging API Integration Guide: REST, SMPP and Webhooks

A messaging API integration guide for developers: REST vs SMPP vs webhooks, authentication, idempotency, delivery receipts, retries, rate limits and testing.

Updated 9 min read

By OmniChannels.ai Editorial Team · Reviewed by BroadNet Messaging Solutions Team

Integration

Short answer

Use a REST API to send messages from applications, SMPP only for high-volume SMS where you already run telecom-grade infrastructure, and webhooks to receive delivery receipts and inbound messages. Authenticate every call, send an idempotency key with each send so retries never duplicate messages, treat delivery status as asynchronous, back off on HTTP 429 and 5xx errors, and test failure paths in a sandbox before production.

On this page
  1. Which interface should you use: REST, SMPP or webhooks?
  2. How should you authenticate?
  3. How do you send a message safely?
  4. Why does idempotency matter?
  5. How do delivery receipts work?
  6. How should you handle retries and rate limits?
  7. How should you test before going live?
  8. Worked example: an OTP and order-notification service
  9. What are the common integration mistakes?
  10. How OmniChannels.ai helps

Key takeaways

  • REST suits most application integrations; SMPP is a persistent binary protocol designed for SMS throughput between messaging systems.
  • An accepted send request means the message was queued, not delivered; final status arrives later through webhooks or SMPP delivery receipts.
  • HTTP 429 Too Many Requests is defined in RFC 6585; clients should slow down and honour any Retry-After header.
  • Idempotency keys let you retry a timed-out send safely without sending the customer the same message twice.
  • Meta signs WhatsApp Cloud API webhooks so receivers can verify that events really came from Meta.

This guide is for backend developers, solution architects and CTOs integrating an application with a messaging provider for WhatsApp, SMS or email. It explains which interface to use, and how to handle authentication, idempotency, delivery receipts, retries, rate limits and testing, with illustrative request and response shapes. For syncing conversations into a CRM, see the companion guide on connecting a CRM with webhooks.

Which interface should you use: REST, SMPP or webhooks?

Use REST to send, webhooks to receive, and SMPP only for high-volume SMS where you already run SMPP. They are complementary rather than competing: most integrations combine REST calls out with webhooks back in.

Aspect REST API SMPP Webhooks
Direction Your app → provider Bidirectional over one session Provider → your app
Transport HTTPS request/response Persistent TCP session, binary PDUs HTTPS POST to your endpoint
Channels WhatsApp, SMS, email, others SMS only All channels' events
Typical use Send messages, manage templates, query status Bulk SMS between messaging systems Delivery status, inbound messages
Strengths Simple, firewall-friendly, rich payloads Throughput, windowing, telecom standard Real-time, no polling
Watch out for Rate limits, timeouts Session management, binds, keep-alives Retries, duplicates, security

SMPP (Short Message Peer-to-Peer) sessions start with a bind (transmitter, receiver or transceiver), send messages with submit_sm, receive delivery receipts and inbound SMS via deliver_sm, and stay alive with enquire_link. It is efficient but operationally heavier than HTTPS.

How should you authenticate?

Use the strongest method the provider offers, keep secrets out of code, and authenticate both directions.

  • Outbound calls: API keys or OAuth 2.0 bearer tokens sent in the Authorization header over TLS. Store them in a secrets manager and rotate on a schedule and after staff changes.
  • SMPP: system ID and password at bind time, typically restricted to allow-listed IP addresses and, where supported, over TLS.
  • Inbound webhooks: verify a signature on every event. Meta signs WhatsApp Cloud API webhook payloads with an HMAC-SHA256 signature in the X-Hub-Signature-256 header, computed with your app secret; providers usually offer a similar scheme. Compute the signature over the raw body before parsing.

Use separate credentials per environment so a leaked test key cannot send production traffic.

How do you send a message safely?

Send through a queue, include an idempotency key, and treat the response as "accepted", not "delivered".

Illustrative send request

The shape below is pseudo-JSON for illustration, not a specific provider's API.

POST /v1/messages
Authorization: Bearer <token>
Idempotency-Key: 7f3c9a2e-order-55821-shipped

{
  "channel": "whatsapp",
  "to": "+9715XXXXXXXX",
  "template": {
    "name": "order_shipped",
    "language": "ar",
    "variables": ["Layla", "55821", "15 March"]
  },
  "client_reference": "order-55821",
  "callback_url": "https://api.example.com/webhooks/messaging"
}

Illustrative response

202 Accepted

{
  "message_id": "msg_01HZX...",
  "status": "accepted",
  "client_reference": "order-55821",
  "created_at": "2026-10-09T12:00:00Z"
}

Store message_id against your own reference immediately. Everything that happens next arrives asynchronously.

Why does idempotency matter?

Because networks time out after the server has already acted. If your send request times out and you retry blindly, the customer may receive two OTPs or two shipping notices. An idempotency key lets the server recognise the retry and return the original result.

Rules that work:

  1. Derive the key from the business event (for example order ID plus event type), not from a random value per attempt.
  2. Reuse the same key for every retry of the same send.
  3. Keep keys long enough to cover your retry window.
  4. If the provider does not support keys, deduplicate on your side before sending.

The IETF's draft Idempotency-Key header standardises this pattern for HTTP APIs; providers' implementations vary, so read their documentation.

How do delivery receipts work?

Delivery status arrives later as events: from webhooks for WhatsApp and most REST APIs, and from deliver_sm receipts on SMPP. Status meanings differ by channel; our guide to message delivery status explains each one.

Illustrative status webhook

POST /webhooks/messaging
X-Signature: sha256=<hmac>

{
  "event_id": "evt_9c1...",
  "type": "message.status",
  "message_id": "msg_01HZX...",
  "client_reference": "order-55821",
  "status": "delivered",
  "timestamp": "2026-10-09T12:00:04Z",
  "error": null
}

Handle status events defensively:

  • Deduplicate on event_id, or on message ID plus status.
  • Never regress a message from read back to delivered when events arrive out of order.
  • Respond with 2xx quickly, then process from a queue.
  • Record error codes for failed messages, and decide which are retryable.
  • Expect gaps: some SMS routes return limited receipts, and read status depends on the channel and the user's settings.

How should you handle retries and rate limits?

Retry only what can succeed, back off exponentially with jitter, and respect the server's signals.

Response Meaning Action
2xx Accepted Store ID, wait for status
400 / 422 Invalid request (number, template, variables) Do not retry; fix data
401 / 403 Auth or permission problem Do not retry; alert
409 Conflict, often a duplicate idempotency key Fetch the original result
429 Too many requests (RFC 6585) Wait for Retry-After or back off
5xx / timeout Server or network error Retry with same idempotency key and backoff

RFC 9110 defines the Retry-After header, which can carry seconds or a date. Put a client-side rate limiter in front of your sends so you stay under the provider's documented limits rather than discovering them through errors. WhatsApp also has Meta-side limits on how many unique customers you can message, described in messaging limits and quality rating.

How should you test before going live?

Test failure paths, not just the happy path.

Pre-production checklist

  1. Send each template with real-length values, including Arabic text.
  2. Force a timeout and confirm the retry does not duplicate.
  3. Send to an invalid number and confirm the error is handled without retry.
  4. Replay a webhook twice and out of order; confirm one final state.
  5. Send a webhook with a bad signature; confirm it is rejected.
  6. Trigger 429s with a load test against the sandbox, if allowed.
  7. Rotate an API key and confirm no downtime.
  8. Check logs contain message IDs but not full message bodies or OTP codes.
  9. Run a small production pilot with internal numbers on each channel.

Sandboxes rarely reproduce carrier and Meta behaviour exactly, so keep monitoring in the first weeks of production.

Worked example: an OTP and order-notification service

"Qafilah Logistics" (synthetic), a parcel company in Saudi Arabia, sends WhatsApp order updates with SMS fallback and authentication OTPs.

  • Architecture: order events go to a queue; a sender worker calls the REST API with an idempotency key of shipment-id:event.
  • Fallback: if WhatsApp returns a failed status for a non-WhatsApp user, the worker sends an SMS with a new key, shipment-id:event:sms.
  • OTP: codes expire quickly, so OTP sends are not retried after the expiry window; the user requests a new code instead. See the OTP authentication messages guide.
  • Receipts: a webhook receiver verifies signatures, deduplicates events and updates a status table that never regresses.
  • Limits: a token-bucket limiter caps send rate per channel below documented limits.

What are the common integration mistakes?

  • Treating "accepted" as "delivered".
  • Retrying with a new idempotency key on every attempt.
  • Doing heavy processing inside the webhook request.
  • Skipping signature verification on webhooks.
  • Retrying 4xx validation errors in a loop.
  • Logging OTP codes and full message content.
  • Using production credentials in test environments.

How OmniChannels.ai helps

OmniChannels.ai, powered by BroadNet Technologies, offers a publicly documented REST/JSON API with an OpenAPI 3.1 spec and a TypeScript SDK, covering SMS, WhatsApp, RCS, Messenger, Instagram, Telegram, email and push, including WhatsApp authentication templates with one-tap, zero-tap and copy-code OTP. Webhooks report delivery statuses in one normalised format, SMPP 3.4 over TLS serves high-volume SMS, and an MCP server connects AI agents. Delivery reports with filters and CSV export help you reconcile what your integration sent. Start with the developer docs and the quickstart.

Frequently asked questions

Should I integrate with a messaging provider through REST or SMPP?

Choose REST for almost all application use cases: it works over HTTPS, is simple to secure and supports rich channels such as WhatsApp. Choose SMPP when you send large SMS volumes, already operate SMPP clients and need a persistent connection with windowing. SMPP applies only to SMS; WhatsApp, email and social channels use HTTP APIs.

What is an idempotency key in a messaging API?

An idempotency key is a unique value your system sends with a request so the server can recognise repeats. If your send call times out and you retry with the same key, the provider returns the original result instead of sending a second message. The IETF has a draft standard for an Idempotency-Key HTTP header, but providers implement keys in different ways, so check the documentation.

Why do delivery reports sometimes arrive out of order?

Status events are generated by different systems, such as carriers, Meta and the provider, and are delivered over networks with retries. A read event can arrive before a delivered event, and duplicates are normal. Store each status with its timestamp, never move a message backwards from a later state to an earlier one, and deduplicate by message ID and status.

How should my application handle rate limits?

Read the provider's documented limits, queue outbound sends instead of firing them directly from user requests, and use a token-bucket or similar limiter on your side. When you receive HTTP 429, pause and retry after the time given in the Retry-After header or with exponential backoff and jitter. Do not retry 4xx validation errors.

What should I test in a messaging sandbox?

Test authentication failures, invalid phone numbers, template variable errors, timeouts with idempotent retries, duplicate and out-of-order webhooks, rate limit responses, long and Arabic messages, and webhook signature verification. Then run a small production pilot with real numbers, because sandboxes rarely reproduce carrier or Meta behaviour exactly.

Sources

  1. Cloud API webhooks — Meta for Developers
  2. RFC 6585: Additional HTTP Status Codes (429 Too Many Requests)
  3. RFC 9110: HTTP Semantics
  4. The Idempotency-Key HTTP Header Field — IETF draft
  5. SMPP protocol specification resources — SMPP.org