Send SMS with FastAPI
Send a booking reminder from a server route, keep the accepted message ID and read its delivery status. This example uses the existing Bird Python SDK.
1. Prepare the workspace
Prepare an SMS-capable US number owned by your workspace, enable the US destination, complete its required sender registration and add balance. The fixed recipient +15005550006 simulates delivery, is billed at the normal destination rate and does not reach a handset. Complete the first-message setup and create a server-side API key before running the application.
2. Create the application
Use Python 3.10 or later and a virtual environment:
Exemple de code
mkdir bird-sms-fastapi
cd bird-sms-fastapi
python3 -m venv .venv
source .venv/bin/activate
python -m pip install messagebird-sdk "fastapi[standard]"
export BIRD_API_KEY="YOUR_API_KEY"
export BIRD_SMS_FROM="YOUR_ELIGIBLE_US_NUMBER"3. Add the routes
Save this as main.py. A lifespan context opens one async SDK client and closes it during shutdown. FastAPI validates the request parameters.
Exemple de code
import logging
import os
from contextlib import asynccontextmanager
from uuid import UUID
from bird import AsyncBird, APIError
from fastapi import FastAPI, Header, HTTPException
sender = os.environ["BIRD_SMS_FROM"]
@asynccontextmanager
async def lifespan(app: FastAPI):
async with AsyncBird(api_key=os.environ["BIRD_API_KEY"]) as client:
app.state.bird = client
yield
app = FastAPI(lifespan=lifespan)
@app.post("/api/sms/messages", status_code=202)
async def send(idempotency_key: str = Header()):
try:
UUID(idempotency_key)
except ValueError:
raise HTTPException(400, "Supply an Idempotency-Key UUID.")
try:
message = await app.state.bird.sms.send(
from_=sender,
to="+15005550006",
text="Your studio visit is tomorrow at 14:00.",
category="transactional",
metadata={"booking": "FN-1042"},
options={"idempotency_key": idempotency_key},
)
return {"id": message.id, "status": message.status}
except APIError:
logging.exception("Bird send failed")
raise HTTPException(503, "Could not confirm the send. Inspect the original attempt before retrying.")
@app.get("/api/sms/messages")
async def read(id: str):
try:
message = await app.state.bird.sms.get(id)
return {"id": message.id, "status": message.status}
except APIError:
logging.exception("Bird read failed")
raise HTTPException(503, "Could not read the message.")4. Run the example
Start the server:
Exemple de code
fastapi dev main.py --host 127.0.0.1In a second terminal, create an operation ID once and send the fixed example:
Exemple de code
export DEMO_OPERATION_ID="$(python3 -c 'import uuid; print(uuid.uuid4())')"
curl -i -X POST http://127.0.0.1:8000/api/sms/messages \
-H "Idempotency-Key: $DEMO_OPERATION_ID"Keep DEMO_OPERATION_ID with this attempt. Do not regenerate it while resolving an uncertain response. The SDK infers the API region from the key.
Inspect the result and recover
The POST returns 202 with the message id and current status. Acceptance precedes delivery. Copy the ID and read it without sending again:
Exemple de code
curl "http://127.0.0.1:8000/api/sms/messages?id=YOUR_MESSAGE_ID"The read returns the recorded status. Follow SMS events for asynchronous outcomes, and use the product log or event guide to investigate a missing receipt. A missing receipt does not establish delivery or failure.
- A missing Idempotency-Key produces 422; a malformed value produces 400 in this application before it calls Bird.
- If the send fails, the application returns 503 and leaves the result unresolved. Inspect the SDK error in the server terminal and the product log. Correct authentication, sender, destination, template or balance errors before retrying.
- For an uncertain response, retain the same key and identical payload. Read the idempotency guide before retrying; a new key creates a new operation, and response retention does not provide an indefinite exactly-once guarantee.
For real reminders, load the booking and its permitted recipient from your database after authorizing the caller. Keep the booking ID with the accepted message ID. Handle replies and opt-outs before adding an automated reply.
These handlers use a fixed test recipient and bind the development server to loopback. Before publishing, authorize each customer action, associate message IDs with the owning account before permitting reads, and apply your application's abuse limits. The booking and workflow are sample application logic.
Continue the integration
- SMS API reference: exact send contract.
- Events and webhooks: verify signatures and retain event identity.
- Migration guides: map an existing provider's behavior.
- SMS resources: setup, operation and comparison paths.
Ressources associées
Poursuivez avec la documentation, les guides et les exemples sur ce sujet. Les ressources sont en anglais.
Regarder le guideSending your first SMSComprendre le conceptWhat does SMS mean?Explorer la fonctionnalitéSMSSuivre le parcours d'apprentissageBuild your first integration
Essayez la pratique et obtenez un guide d'implémentation