Automate receiving SMS codes: polling or webhooks
Quick answer
The Noir SMS API gives you two ways to get the code automatically. Polling: call GET /api/v1/numbers/{id} every 3 to 5 seconds until status is received. Webhooks: set an HTTPS URL in the dashboard and receive a POST with type sms.received as soon as the SMS is detected. Verify the X-NoirSMS-Signature header, which is an HMAC-SHA256 of the timestamp and raw body, and reject events older than 5 minutes.
Polling is easiest for scripts. Webhooks scale better when many numbers are open at once.
Which to choose
| Polling | Webhook | |
|---|---|---|
| Setup | None | Public HTTPS endpoint |
| Latency | Your polling interval | Seconds |
| Rate limit use | One request per poll | None |
| Best for | Scripts, CLI tools | Panels, bots, many numbers |
Webhook receiver in Python
The header has the form t=<unix time>,v1=<signature>. We retry once after 3 seconds if your server fails, so respond with any 2xx quickly.
import hmac, hashlib, time, os
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["NOIRSMS_WEBHOOK_SECRET"]
def valid(raw: bytes, header: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
expected = hmac.new(SECRET.encode(), f"{parts['t']}.".encode() + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
@app.post("/noirsms")
def hook():
if not valid(request.get_data(), request.headers.get("X-NoirSMS-Signature", "")):
abort(401)
event = request.get_json()
if event["type"] == "sms.received":
d = event["data"]
save_code(d["number_id"], d["sms"]["code"]) # your own storage
return "", 204Combine them
Use webhooks as the main path and a slow poll (for example every 30 seconds) as a fallback for missed deliveries.
Use it responsibly
Use the API only for your own legitimate accounts or apps you're authorized to test, and make sure your customers follow the same Acceptable Use Policy.
Frequently asked questions
Do webhooks fire for dashboard purchases?
Webhooks are for numbers bought through the API.
What if my endpoint is down?
We retry once. Keep a fallback poll for numbers still open.
Services in this guide
Keep reading
Receive SMS verification codes with Python
Buy a temporary number and read the SMS verification code from Python with the Noir SMS REST API. Full example with requests, polling and errors.
Read the guide →DevelopersCommon Noir SMS API errors and how to handle them
Every Noir SMS API error code explained: invalid_api_key, insufficient_balance, no_numbers, too_early, rate_limited and more, with a retry pattern.
Read the guide →DevelopersBuilding an SMS verification panel on the Noir SMS API
How to build your own SMS verification panel or reseller site on the Noir SMS API: architecture, database, webhooks, pricing and abuse rules.
Read the guide →DevelopersUsing virtual numbers to test SMS flows
How QA teams use real virtual numbers to test SMS sign-up and OTP flows end to end, when to use them vs test numbers, and how to automate with an API.
Read the guide →DevelopersReceive SMS verification codes with Node.js
Buy a temporary number and read SMS verification codes from Node.js with fetch and the Noir SMS REST API. Complete example with error handling.
Read the guide →DevelopersReceive SMS verification codes with PHP
Use PHP and cURL to buy a temporary number and read the SMS verification code with the Noir SMS API. Copy-paste example for panels and scripts.
Read the guide →