Send SMS with Next.js
Send a booking reminder from a server route, keep the accepted message ID and read its delivery status. This example uses the existing Bird TypeScript 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 Node.js 20.9 or later with the App Router:
Ejemplo de código
npx create-next-app@latest bird-sms-next --yes --ts --eslint --no-tailwind --app --no-src-dir --use-npm --disable-git
cd bird-sms-next
npm install @messagebird/sdkCreate .env.local beside package.json and keep it out of version control:
Ejemplo de código
BIRD_API_KEY=YOUR_API_KEY
BIRD_SMS_FROM=YOUR_ELIGIBLE_US_NUMBERDo not prefix these server credentials with NEXT_PUBLIC_. Restart the development server after changing them.
3. Add the route
Create app/api/sms/messages/route.ts. The POST sends a fixed example; the GET reads an existing message. This uses the standard Next.js route handler interface.
Ejemplo de código
import { BirdClient } from "@messagebird/sdk";
export const runtime = "nodejs";
function required(name: string): string {
const value = process.env[name];
if (!value) throw new Error(`Configure ${name}.`);
return value;
}
const sender = required("BIRD_SMS_FROM");
const bird = new BirdClient({ apiKey: required("BIRD_API_KEY") });
const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
export async function POST(request: Request) {
const key = request.headers.get("Idempotency-Key");
if (!key || !uuid.test(key)) {
return Response.json({ error: "Supply an Idempotency-Key UUID." }, { status: 400 });
}
try {
const message = await bird.sms.send(
{
from: sender,
to: "+15005550006",
text: "Your studio visit is tomorrow at 14:00.",
category: "transactional",
metadata: { booking: "FN-1042" },
},
{ idempotencyKey: key },
);
return Response.json({ id: message.id, status: message.status }, { status: 202 });
} catch (error) {
console.error(error);
return Response.json(
{ error: "Could not confirm the send. Inspect the original attempt before retrying." },
{ status: 503 },
);
}
}
export async function GET(request: Request) {
const id = new URL(request.url).searchParams.get("id");
if (!id) return Response.json({ error: "Supply a message id." }, { status: 400 });
try {
const message = await bird.sms.get(id);
return Response.json({ id: message.id, status: message.status });
} catch (error) {
console.error(error);
return Response.json({ error: "Could not read the message." }, { status: 503 });
}
}4. Run the example
Start the server:
Ejemplo de código
npm run dev -- --hostname 127.0.0.1In a second terminal, create an operation ID once and send the fixed example:
Ejemplo de código
export DEMO_OPERATION_ID="$(python3 -c 'import uuid; print(uuid.uuid4())')"
curl -i -X POST http://127.0.0.1:3000/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:
Ejemplo de código
curl "http://127.0.0.1:3000/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 or malformed Idempotency-Key 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.
Recursos relacionados
Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.
Ver la guíaSending your first SMSComprender el conceptoWhat does SMS mean?Explorar la funcionalidadSMSSeguir la ruta de aprendizajeBuild your first integration
Prueba el ejercicio y obtén un resumen de implementación