Documentation
Sign inGet started

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/sdk
Code 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