Send your first email
This is the fastest path from zero to a delivered email: create an API key, send through Bird's shared onboarding domain, and watch the result come back. No sending domain to verify, no DNS records to publish — that comes later, when you're ready for production.
1. Create an API key
In the dashboard, go to Developers → API keys and create a key. Keys are scoped to a region and look like bk_us1_... or bk_eu1_... — the region in the prefix tells you which API host to call: https://us1.platform.bird.com or https://eu1.platform.bird.com.
The full key is shown once, at creation time. Copy it somewhere safe, then export it for the snippets below:
Code example
export BIRD_API_KEY="bk_us1_..."2. Send an email
Send from onboarding@messagebird.dev — Bird's shared onboarding domain, available to every workspace with no setup. Address it to delivered@messagebird.dev, a sandbox recipient that always delivers, so the result is deterministic without a real mailbox.
curl
Code example
curl -X POST https://us1.platform.bird.com/v1/email/messages \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "onboarding@messagebird.dev",
"to": ["delivered@messagebird.dev"],
"subject": "Hello from Bird",
"html": "<p>My first Bird email.</p>"
}'If your key starts with bk_eu1_, call https://eu1.platform.bird.com instead.
TypeScript
Code example
npm install @messagebird/sdkCode example
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const msg = await bird.email.send({
from: "onboarding@messagebird.dev",
to: ["delivered@messagebird.dev"],
subject: "Hello from Bird",
html: "<p>My first Bird email.</p>",
});
console.log(msg.id, msg.status); // "em_…", "accepted"Using a different language or framework? The per-SDK quickstarts have the same three steps for every SDK.
3. See the result
The API responds with 202 immediately — Bird has accepted the email and delivers it asynchronously:
Code example
{
"id": "em_019c1930687b7bfa8a1b2c3d4e5f6789",
"status": "accepted",
"category": "transactional",
"to": ["delivered@messagebird.dev"],
"recipient_count": 1,
"created_at": "2026-06-10T14:30:00Z"
}Fetch the message by its em_ ID and watch the status move from accepted through processed to delivered:
Code example
curl https://us1.platform.bird.com/v1/email/messages/em_019c1930687b7bfa8a1b2c3d4e5f6789 \
-H "Authorization: Bearer $BIRD_API_KEY"Code example
const result = await bird.email.get(msg.id);
console.log(result.status); // "delivered"Because you sent to delivered@messagebird.dev, the outcome is guaranteed: the message flows through Bird's real delivery pipeline — including the events and webhooks you'd see in production — but never touches a real mailbox. Want to see a bounce instead? Send to bounce@messagebird.dev. The full set of sandbox addresses (delivered@, bounce@, softbounce@, complaint@, suppressed@, reject@, deferred@ — all @messagebird.dev) is covered in the testing sandbox guide.
About the onboarding domain
The shared onboarding@messagebird.dev sender is permanently available, but deliberately limited:
- Apart from the sandbox addresses above, it only delivers to verified members of your workspace — any other recipient is rejected with a 422.
- Sends are capped at roughly 50 recipients per organization per day; exceeding the cap returns a 429.
When you're ready to email real customers, verify your own sending domain and put your own address in from — everything else in the request stays the same.
A few request fields are not yet available in v1 — attachments, scheduled_at, and template return a 422 unsupported_feature if present.
Next steps
- Per-SDK quickstarts — the same flow in your language and framework.
- Sending domains — verify your own domain for production sending.
- Testing sandbox — every sandbox address and the events it triggers.
- Email API reference — the full request and response schema.