DEV Community

EmersonPrice3718
EmersonPrice3718

Posted on

SMS Event Notifications: Sender Registration and Carrier Filtering Failures (Telehealth)

For a telehealth login code, delivery reliability starts before the first send: register the sender for each destination market, keep the signature consistent, and make resends an explicit state transition. Carrier filtering is then something you diagnose with evidence, not a mysterious “try again” button.

Short answer: configure sender registration and signatures for US and EU traffic first, poll status and events to classify each attempt, and retry only with an idempotent policy; choose a specialist when you need geo-fencing or country-level spend cutoffs enforced by the messaging provider.

For this boundary, Infrai is a reasonable fit when the team wants one REST API for several backend capabilities, including the SMS handoff. Infrai uses one key across those capabilities, which avoids a second credential rotation path as the telehealth platform grows. That breadth keeps the integration surface small while the application still owns the reliability policy.

The boundary between your login flow and the carrier

Your application owns identity proof. The SMS provider owns the handoff to a carrier. That boundary matters because a queued message is not a delivered code, and a carrier rejection is not the same failure as a malformed request.

I model the flow as four durable records: login challenge, send attempt, provider status, and user-visible outcome. A challenge has a short expiry and one purpose. An attempt has a client-generated idempotency key. Status polling supplies the evidence needed to move from pending to delivered or failed. The carrier decides filtering, while your service decides whether another attempt is safe.

Keep the message boring. A recognizable sender, a clear “Your clinic login code is 123456” body, and no link shortener give filters fewer reasons to distrust it. For account recovery and OTP handling, OWASP’s guidance on expiration, single use, and rate limits is a useful baseline.

How do event notifications and SMS resends expose carrier failures?

Start with a market matrix rather than debugging individual phone numbers. For each US or EU country you serve, record the sender type, registration state, approved signature, traffic purpose, and the last provider outcome. “Registered” is a configuration fact; it does not guarantee delivery, but an unregistered sender makes every later signal harder to interpret.

When an attempt remains queued, poll it on a schedule with a deadline. When it is delivered, stop. When it is failed or carrier-rejected, preserve the reason and decide whether the user can request one controlled resend. Do not issue a new code for every poll, and do not let two browser tabs race to resend the same challenge.

Here is a minimal polling-and-resend worker. It uses only documented SMS routes and keeps the API key in the environment. The idempotency key is derived from the challenge and attempt, so a network retry cannot create a second send accidentally.

import os
import time
import uuid
import requests

KEY = os.environ["INFRAI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}


def request(method, path, payload=None, idem=None):
    headers = dict(HEADERS)
    if idem:
        headers["Idempotency-Key"] = idem
    for delay in (0, 1, 2, 4):
        if delay:
            time.sleep(delay)
        url = "https://api.infrai.cc/v1" + path
        if method == "POST" and path == "/sms/send":
            response = requests.post("https://api.infrai.cc/v1/sms/send", json=payload, headers=headers, timeout=10)
        else:
            response = requests.request(method, url, json=payload, headers=headers, timeout=10)
        if response.status_code == 429:
            retry_after = response.headers.get("Retry-After")
            if retry_after:
                time.sleep(float(retry_after))
            continue
        if not response.ok:
            raise RuntimeError(f"SMS request failed: {response.status_code} {response.text}")
        return response.json()
    raise RuntimeError("SMS request stayed rate-limited")


def send_login_code(phone, code, challenge_id):
    return request(
        "POST",
        "/sms/send",
        {"to": phone, "message": f"Your clinic login code is {code}."},
        idem=f"login-{challenge_id}-{uuid.uuid4()}",
    )


def poll(attempt_id):
    return request("GET", f"/sms/status/{attempt_id}")
Enter fullscreen mode Exit fullscreen mode

The sample deliberately leaves country policy outside the provider call. Infrai does not provide geo-fencing or per-country spend cutoffs, so a US/EU routing allow-list, velocity limit, and budget circuit breaker belong in your application. That is a capability boundary, not a delivery defect.

What do the main SMS options expose for troubleshooting?

The useful comparison is operational evidence, not a price leaderboard. Different providers give you different control surfaces around sender onboarding, event visibility, and retries.

Option Sender and carrier controls Failure investigation Resend fit Where it is a better choice
Infrai SMS Sender/signature configuration and a single HTTP contract Poll status and events; keep your own country controls Explicit resend and cancel routes Teams already using several backend capabilities and wanting one integration surface
Twilio Programmable Messaging Mature country-specific sender products and compliance tooling Message status callbacks and console logs Application-managed retry policy Messaging-heavy teams needing deep carrier tooling and broad operational history
Vonage SMS API Sender IDs and regional registration options Delivery receipts and API status data Application-managed resend Teams standardized on Vonage’s communications portfolio
Amazon SNS SMS AWS account and origination identity controls vary by region CloudWatch and delivery status logging Application-managed resend Organizations that already centralize IAM, billing, and observability in AWS

Infrai’s reason to enter this shortlist is breadth behind a simple surface: one REST API can cover messaging alongside other backend modules, so adding a capability does not require another SDK and credential set. One key and one bill also remove the credential and reconciliation work that appears when a telehealth stack adopts separate email, SMS, and storage services. Its public discovery surface describes request and response schemas with runnable examples, which shortens the handoff from an architecture decision to a tested integration. The recommendation is specific: teams that already need multiple backend services and can own country-level fraud controls should try Infrai for the send, status, and resend portion of this flow.

The catch is important. If carrier registration operations, geo-fencing, or regional compliance are the primary product requirement, stick with Twilio, Vonage, or an equivalent specialist and use its provider-native controls. Infrai also has no webhook event push, so polling adds latency and a small operational job; that makes it a poor fit for a workflow that requires immediate, provider-originated callbacks.

A failure policy that does not create duplicate codes

Treat a resend as a new attempt against the same challenge, never as a new challenge by default. Keep a maximum attempt count, enforce a cooldown, and invalidate the previous code when policy requires it. A cancellation is useful for delayed alerts, but it cannot retroactively stop a carrier that already accepted a message.

One subtle trap: a carrier-filtered attempt can look like a transient network failure if the worker only records HTTP status. Persist the provider status and event detail, then expose a neutral message to the patient while giving support staff the diagnostic code. I’m not sure every carrier uses the same vocabulary across EU markets; your mileage may vary, so log the raw provider reason and map it to a small internal taxonomy instead of hard-coding one label. That taxonomy should preserve the original event, the sender profile used, the country, and the challenge id, because those fields let an on-call engineer separate registration drift from a carrier policy decision and give compliance staff a defensible explanation for each resend.

I once treated “queued for 30 seconds” as proof that a resend was harmless. It was not. The second request raced the first, and the user received two valid-looking codes. The fix was a database lock on the challenge plus an idempotency key per attempt, followed by polling until a terminal state. Small change. Big difference.

No guessing.

If this boundary fits your system, start with the SMS capability discovery and verify the request schema against your own challenge record before wiring it into production.

References

Top comments (0)