API Integrations Masterclass · Chapter 1 · 12 min
Anatomy of a messaging API
Resources, verbs, status codes and the asynchronous lifecycle behind every 202 Accepted.
The resource model
A messaging API is a thin synchronous facade over an asynchronous machine at the heart of ub3r. When you POST to /v1/messages, nothing has been delivered yet because the provider has merely validated your request. That is why well-designed APIs answer with 202 Accepted rather than 200 OK. You should design your system to expect this delay and handle it gracefully without blocking your main application thread.
Core Messaging Nouns
The core resources are almost always the same: a Message, a Recipient, a Channel, and a Status event. Everything else like templates or sender IDs is metadata hung on those four nouns. Understanding how these nouns interact is key to building a robust integration that scales across regions. Each resource has a unique identifier that you should store in your database for future reconciliation.
POST /v1/messages HTTP/1.1
Authorization: Bearer sk_live_...
Content-Type: application/json
Idempotency-Key: 8c1e3a7e-6b0f-4b3d-9d61-2f6a1c0d4e11
{ "to": "+56912345678", "channel": "sms", "text": "Your code is 481 223" }The delivery lifecycle
After acceptance a message walks a state machine: queued → sent → delivered, with failed and undelivered as terminal branches. sent means the provider handed it to a carrier; delivered means the downstream network confirmed receipt. These are different facts from different systems, and they arrive at different times. Your application logic must be prepared to handle these transitions and potentially out-of-order notifications from the platform.
Status codes that matter
Classifying responses into *retryable* and *terminal* is the first piece of logic every integration needs. Get it wrong and you either drop messages or send the same OTP four times, leading to a poor user experience. A 400 means your payload is malformed and you should never retry without changing it. Conversely, a 429 means you are being rate limited and should respect the Retry-After header provided by the server.
Reliability at the Edge
Validation belongs at the edge of your system, where the human typed it, not deep inside a worker. Normalise numbers to E.164 format before they ever reach the API call to ensure maximum compatibility. Some providers will silently accept and misroute a number missing its country code, which is hard to debug. By cleaning data early, you ensure that the ub3r API receives high-quality input that results in successful delivery.
Discussion (3)
The distinction between 'sent' and 'delivered' finally clicked for me here. We had dashboards treating them as the same thing for a year.
Good point — we're adding a short section on this in the next revision.
Would love a follow-up on how this behaves under carrier throttling. We see very different numbers per route.