# Send email · One API for transactional and marketing mail

## Already sending through SMTP?

Keep your existing SMTP client and connect it to Bird’s relay. Use the SMTP setup page for regional hosts, TLS ports and authentication. If your application needs to receive and parse messages, start with inbound email.

[Set up SMTP relay](/email-api/features/smtp)

[Receive inbound email](/email-api/features/inbound)

## Send your first email in five minutes.

## From the language you already use.

Sending is the core of the [Bird Email API](/email-api). Your first send can go to a sandbox address (delivered@messagebird.dev), so you can exercise the whole platform (sends, webhooks, suppression) before you verify a domain.

**Node.js**: `npm install @messagebird/sdk`

```typescript
const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  subject: "Hello from Bird",
  html: "<p>My first Bird email.</p>",
});
console.log(msg.id, msg.status); // "em_…", "accepted"
```

Examples: [TypeScript](/de-de/email-api/features/sending.ts.md) · [Python](/de-de/email-api/features/sending.py.md) · [Go](/de-de/email-api/features/sending.go.md) · [PHP](/de-de/email-api/features/sending.php.md) · [CLI](/de-de/email-api/features/sending.cli.md) · [MCP](/de-de/email-api/features/sending.mcp.md) · [cURL](/de-de/email-api/features/sending.curl.md)

## Five things you don't build yourself.

The same contract on every Bird channel.

- **01** Transactional + marketing. The same endpoint sends a password reset or a campaign. A category field decides how suppression and unsubscribes apply.
- **02** Templates your way. Pass raw HTML, render React Email templates to HTML in your app and send the result, or name a stored template and have it rendered for you. Your toolchain, unchanged.
- **03** Batch up to 100. Up to 100 independent messages per call, each with its own recipient and variables, validated as one unit so you never half-send.
- **04** Idempotent by contract. Every send accepts an idempotency key, so a retried request after a timeout returns the original result instead of double-sending.
- **05** A webhook on every state change. Accepted, delivered, opened, clicked, bounced, complained. Each one HMAC-signed, replay-protected, idempotent, the same envelope on every channel.

## Make the first request from your application.

Create an account and API key, then follow the sending guide with a test recipient.

[Start for Free](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Femail)

## One message or a hundred, one call.

Batch up to 100 independent messages in one request, each with its own recipient and variables. The batch validates as a unit: one bad message rejects the call with a 422, so you never half-send. A single idempotency key makes the whole request safe to retry.

**digest.ts**

```typescript
import { BirdClient } from "@messagebird/sdk";
import { render } from "@react-email/render";
import { Digest } from "./emails/digest";

const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });

const messages = await Promise.all(
  users.map(async (u) => ({
    from:    "Acme <hello@yourdomain.com>",
    to:      [u.email],
    subject: "Your weekly digest",
    html:    await render(<Digest user={u} />),
  })),
);

const { data: batch, error } = await bird.email
  .sendBatch(messages, { idempotencyKey: `digest-${runId}` })
  .safe();

if (error) throw error;
console.log(`queued ${batch.data.length} messages`);
```

## Attach your own context to every send.

Tags are a first-class, filterable dimension: slice delivery and engagement by campaign, template, or experiment in the stats API (up to 20 per message). Metadata is arbitrary JSON, up to 2 KB, that round-trips untouched on every read and webhook, so your own IDs ride along with the message.

**tagged.ts**

```typescript
await bird.email.send({
  from:     "Acme <hello@yourdomain.com>",
  to:       ["delivered@messagebird.dev"],
  subject:  "Your invite is ready",
  html:     "<p>Welcome aboard, Ada.</p>",
  tags:     [{ name: "campaign", value: "spring-2026" }],
  metadata: { user_id: "u_2bX91", order_id: "ord_5512" },
});
```

## Test every outcome before you go live.

In the sandbox the recipient address decides the result, so your account state doesn't have to. Send to delivered@messagebird.dev for a clean delivery, or to bounce@, softbounce@, deferred@, complaint@, and suppressed@ to drive each failure path through the real pipeline and the real webhooks. No domain to verify, no risk to your reputation. Production is deliberately gated: you verify a domain first, and a new domain or dedicated IP ramps through warmup before it carries full volume.

## Go deeper in the docs.

Read the [sending guide](/docs/guides/email/sending-email), wire up [email events and webhooks](/docs/guides/email/events), or, if you're coming from another provider, follow a [migration guide](/docs/guides/email/migrate) from SendGrid, SES, Mailgun, or Resend.

## Test the behavior around the send.

A working send call is the beginning of an integration. Rehearse bounces and complaints, handle duplicate webhook deliveries and decide how your application schedules messages or receives replies.

## Continue with the workflow you need

Choose the product or guide that matches the next job.

- [Email sandbox](/docs/guides/email/testing-sandbox): Exercise delivery outcomes with documented test addresses.
- [Scheduled messages](/docs/guides/email/scheduled-sending): Set a future time for inline content and understand cancellation.
- [Batch sending](/docs/guides/email/sending-bulk): Submit independent messages together for a one-off recipient list.
- [Email integration library](/email-api/resources): Find setup, migration and troubleshooting guides.

161%

Increase in email open rates reported in Zillow’s customer story.

[Read the Zillow story](/customers/zillow)

## When the right home appears, the email needs to arrive.

Zillow brought time-sensitive property alerts to Bird, with the capacity to handle sending surges and the analytics to understand engagement. Its team reported a 161% increase in open rates in the first month.

Planning a migration or a higher-volume send?

[Contact sales](/demo?product=email&source_page=%2Femail-api%2Ffeatures%2Fsending)

## Questions about sending email

### Can I send both transactional and marketing email?

Yes, both go through the same send API. The only difference is the category field, which decides how suppressions and unsubscribes apply. Pick transactional for password resets and receipts, and marketing for campaigns.

### What happens if a request times out and I retry it?

Send an Idempotency-Key header with each logical send. If the first request succeeded but you never saw the response, replaying it with the same key gives you the original result back with an Idempotency-Replay header, rather than sending the email twice.

### Can I schedule a send for later?

Set scheduled_at to any time between 30 seconds and 30 days ahead. The send comes back accepted straight away and stays scheduled until it goes out, so you can cancel it at any point before then.

### Can I attach files?

Yes, as base64 in the attachments array. To show an image inline, give it a content_id and reference that from your HTML with cid:. Keep the raw files at or below 15 MB so the message still fits the 20 MB cap once it is encoded, and note that executable and script content types are refused before the send.

## Connect sending to the rest of your workflow

- [Templates](/email-api/features/templates): Stored, versioned email templates, personalized per recipient at send.
- [Deliverability](/email-api/features/deliverability): Authentication, managed IP warmup, recipient suppressions and delivery signals.
- [Analytics](/email-api/features/analytics): Delivery by domain, provider and IP, with separate engagement breakdowns.
- [Email API overview](/email-api): The full Email API: sending, deliverability, IPs, suppression, analytics, and broadcasts.

Talk to our email team

## Build your next email integration.

Talk through transactional messages, batch sends and delivery events. We’ll help you plan your integration, sending volume and migration.

[Follow the first-send guide](/docs/get-started/send-your-first-email)

Create your account, then create an API key and send a test message.

## Scale without  losing control.

Organize teams in workspaces, control API access, and trace changes through audit logs.

Harbor Organization
Workspaces Production Sandbox

### Delivery agent

API key · Customer operations team
Active
Permissions Access
Email Read & write
SMS Read & write
WhatsApp Read Read & write
AL Alex Lee Admin  Permissions updated

### Audit log

Production
 API key updated Alex Lee · 09:42:18 UTC

Workspace
Production

Resource
Delivery agent

WhatsApp
Read Read & write

Succeeded

 [Workspaces](/docs/guides/workspaces)[Team roles](/docs/guides/users-teams-roles)[API authentication](/docs/guides/authentication)
[Explore Enterprise](/enterprise)

## Start with Email. Build across channels with Bird.

[Get started](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Femail) · [Contact Sales](/demo?product=email)

[Email](/email-api) · [SMS](/sms-api) · [WhatsApp](/whatsapp-api) · [Apple Messages](/apple-messages-api) · [Voice](/voice-api)



## Related resources

- [Getting started with email](/learn/email/getting-started-with-email) (video)
- [Build your first integration](/learn/paths/integration) (course)

[Get an implementation brief](/learn/workspace?topic=email)
