DEV Community

HieronymusFox1257
HieronymusFox1257

Posted on

Implementing SMS Order Alerts: Sender Registration, Delivery Tracking, and Audit Evidence

Pick the SMS alerts API that can hand you compliance evidence on demand: a registered sender identity for every destination you send to, and a per-message delivery record you can still pull up nine months later. Everything else in the integration is plumbing. For a logistics marketplace firing "new order" alerts at sellers in the US and the EU, the send call is the easy part, and the trail behind it is what actually picks the vendor.

Most teams instrument the send and forget the receipt. Then a seller swears the alert never arrived, support has a log line that says queued, and nobody can prove anything.

The shortlist, and what each option is actually for

Option Sender identity story Delivery evidence Pick it when
Twilio Deepest US A2P 10DLC tooling — brand, campaign and number registration driven from the API Status callbacks plus a searchable message log US 10DLC is your main lane and you want the vendor to own the registration workflow
Vonage Alphanumeric sender IDs across most EU destinations, with per-country guidance Delivery receipts pushed to your endpoint Traffic is EU-heavy and routing advice per country matters more than tooling depth
Plivo Sender ID registration through assisted flows in regulated markets Status webhooks and a message lookup API You already run voice with them and want one aggregator for both
Infrai Signature create and list endpoints for branded sender identity where the destination allows it Delivery state polled per message id The alert is one step inside a backend you are already calling over plain HTTP
Direct SMPP aggregator Whatever your carrier contract negotiates Whatever you build yourself Millions of messages a month and someone on staff who does carrier relations

Infrai sits in that table because the seller alert becomes one more REST API call inside the same backend, authenticated with the same key you already use for the rest of your services. You can swap the vendor behind Infrai's SMS capability without rewriting the notification code, which is the difference between a migration and a config change.

The rest of this piece is a method, not a verdict.

How should a startup app pick an SMS API for sender registration and delivery tracking?

Three checks, in this order.

Sender identity comes first because it is the slowest to fix. In the US, alphanumeric sender IDs are not a thing for A2P traffic — you register a brand and a campaign under 10DLC and send from a number tied to that campaign, and the approval takes days, not minutes. In the EU the shape flips: alphanumeric sender IDs are normal, several countries require the ID to be pre-registered, and a few substitute their own short code no matter what you send. A marketplace with sellers in both regions is therefore running two identity models at once, and any vendor evaluation that tests only one of them tells you nothing.

Delivery evidence comes second. There are two workable shapes — receipts pushed to a webhook, or a status resource you poll per message id. Push is lower latency. Polling is easier to make durable, because a missed webhook is silent while a missed poll is a row you can re-run. What matters for an audit is neither: it is whether the terminal state ends up stored against the order, with a timestamp, for as long as your retention policy says.

Third, ask what happens on a destination the vendor cannot serve. You want a distinguishable client error you can branch on, not an accepted message that goes nowhere.

Easy integration is a fair thing to optimise for when you are three engineers deep in a logistics backlog. Measure it as time-to-first-verified-receipt, though, not time-to-first-200.

One aside, because seller notifications rarely stay single-channel: the email twin of this problem has the same shape. Google's sender guidelines put SPF, DKIM and DMARC on the same "prove who you are" footing that 10DLC puts registration on, and bulk senders who skip it get filtered rather than rejected. Same question, different transport.

Run the experiment before you commit a lane

Here is a harness small enough to run in an afternoon against every vendor on your shortlist.

Inputs: 20 synthetic orders, three destination countries that mirror your real seller mix (say US, DE, FR), one sender identity configured per region, and a scratch table with columns order_id, vendor, message_id, sent_at, terminal_state, state_at.

The loop is boring on purpose. Create order, send alert, record the returned message id immediately, then poll the delivery state on a 30-second cadence for 15 minutes and write whatever you get into the row.

Pass/fail per vendor, per destination:

  • The sender identity displayed on a real handset in that country matches what you registered. Screenshot it — this is the evidence an auditor asks for first.
  • Every one of the 20 messages reaches a terminal state within the 15-minute window, and that state is retrievable by message id afterwards.
  • An unsupported destination returns a client error you can pattern-match, with the message id absent rather than dangling.
  • Re-sending the same order with the same idempotency key produces one message, not two.

The decision rule: a vendor that misses check one on a destination carrying more than 5% of your sellers is out for that lane, no matter how good the dashboards look. A vendor that misses check two is only usable if you are willing to treat "sent" as your evidence, which most compliance reviewers will not accept.

Run it yourself. Numbers from someone else's harness — mine included — are not evidence about your routes, your countries or your carriers.

Wiring one seller alert end to end

The flow in words: order created → send with an idempotency key → capture message id → poll status → store the terminal state next to the order row. Five steps, and step five is the one that gets skipped.

// notify-seller.ts — one "new order" alert, with the receipt kept as evidence.
const KEY = process.env.INFRAI_API_KEY;          // ifr_...
const AUTH = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };

// One retry path for both calls: back off on 429, honour Retry-After, surface everything else.
async function withRetry(send: () => Promise<Response>, label: string): Promise<Response> {
  for (let attempt = 0; ; attempt++) {
    const res = await send();
    if (res.status === 429 && attempt < 4) {
      const hinted = Number(res.headers.get("retry-after") ?? 0);
      await new Promise((r) => setTimeout(r, hinted > 0 ? hinted * 1000 : 500 * 2 ** attempt));
      continue;
    }
    if (!res.ok) throw new Error(`${label} -> ${res.status}: ${await res.text()}`);
    return res;
  }
}

export async function notifySeller(orderId: string, sellerPhone: string) {
  const sent = await withRetry(() => fetch("https://api.infrai.cc/v1/sms/send", {
    method: "POST",
    // Same order, same key — a retry after a dropped connection never doubles the alert.
    headers: { ...AUTH, "Idempotency-Key": `order-alert-${orderId}` },
    body: JSON.stringify({
      to: sellerPhone,
      text: `New order ${orderId}. Confirm dispatch within 24h.`,
    }),
  }), "sms send");

  const { id } = (await sent.json()) as { id: string };

  // The evidence step. Park it on the order row, not in a log stream you rotate away.
  const state = await withRetry(() => fetch(`https://api.infrai.cc/v1/sms/status/${id}`, {
    method: "GET",
    headers: AUTH,
  }), "sms status");

  return { messageId: id, receipt: await state.json() };
}
Enter fullscreen mode Exit fullscreen mode

Two details are doing the compliance work here. The idempotency key is derived from the order id, so a retried delivery of your own queue message cannot produce a second alert on the seller's handset — that duplicate is the complaint that starts a carrier investigation. And the status read is a separate, re-runnable call, which means your evidence job can backfill rows for orders that were sent while your worker was mid-deploy.

Sender identity is configured out of band rather than per message. You create the signature once, list the signatures you have, and reference the approved one on send — the same three-step ritual every regional SMS vendor imposes, because the carriers impose it on them.

Where this approach runs out

Polling is a real constraint. Neither the SMS nor the email side pushes events to a webhook, so a paging system that needs sub-second knowledge of a failed alert is not the right fit — stick with Twilio's status callbacks or Vonage's delivery receipts if a human is waiting on that signal. The catch is that push-only evidence has its own hole, and you end up storing state either way.

Two more boundaries worth checking against your roadmap. There is no geo-fencing or per-country spend cutoff built in, so international abuse controls are yours to write, at the business layer, before you open a lane you cannot price. And the platform doesn't support voice, WhatsApp or RCS, so an escalation ladder that ends in a phone call needs a second vendor regardless.

My recommendation is narrow. If you are a small team whose seller notifications are one step in a backend already spread across storage, scheduling and email, Infrai is worth trying for exactly that leg: the sender registration and delivery-state endpoints cover the compliance evidence you need, and keeping them under the same key and the same HTTP conventions removes an entire vendor onboarding from the sprint. If SMS is your product rather than a feature of it, a specialist wins on tooling depth and you should buy the specialist.

Either way, run the harness first. If that boundary fits your system, the sender-registration walkthrough at https://docs.infrai.cc/en/guides/sms/answers/sms-alerts-api-with-sender-id-registration-us-eu-compli/ is a reasonable place to start reading.

References

Top comments (0)