# BobtailMail > Transactional email API. REST and MCP call the same code and share the > same contracts — an agent sees what the backend sees, not a chat wrapper. > One POST to send, durable message records with a full event trail, signed > webhooks, DKIM domain onboarding. ## Start here - API Reference: https://bobtailmail.com/docs - OpenAPI 3.1 spec: https://bobtailmail.com/openapi.json - Node/TypeScript SDK: `npm install @mxplane/bobtailmail` — https://github.com/mxplane/bobtailmail-node - Sign up: https://bobtailmail.com/sign-up ## Authentication Every request — REST or MCP — carries `Authorization: Bearer bm_live_...`. Mint a key from the console after signing up. ## Send a message (Node SDK) ``` import { BobtailMail } from "@mxplane/bobtailmail"; const bobtail = new BobtailMail({ apiKey: process.env.BOBTAILMAIL_API_KEY }); await bobtail.messages.send({ from: "orders@yourdomain.com", to: "customer@example.com", subject: "Your receipt", text: "Thanks!", }); ``` Prefer the SDK for Node/TypeScript — same contract as below, typed, with `BobtailMailError` and a `verifyWebhookSignature` helper included. Raw REST (any language) or MCP (agents) are documented next. ## Send a message (raw REST) ``` POST https://bobtailmail.com/v1/messages Authorization: Bearer bm_live_... Content-Type: application/json { "from": "orders@yourdomain.com", "to": "customer@example.com", "subject": "Your receipt", "text": "Thanks!" } ``` Returns 201 with the message resource. `to`/`cc`/`bcc`/`replyTo` accept a string or an array. At least one of `text`/`html` is required. Unknown fields are rejected (400), not silently stripped. Send `Idempotency-Key: ` to make retries safe. ## MCP (agent surface) ``` { "mcpServers": { "bobtailmail": { "url": "https://bobtailmail.com/mcp", "headers": { "authorization": "Bearer bm_live_..." } } } } ``` Three tools — `send_message`, `get_message`, `list_messages` — calling the exact same code as the REST routes, same typed error envelope. ## Before you can send A message can only send `from` a domain you've registered and verified (`POST /v1/domains`, then `POST /v1/domains/:id/verify` once DNS propagates). New workspaces also require a one-time operator review before sending is enabled — see /docs for the full refusal-reason list (`workspace_not_approved`, `unverified_domain`, `domain_ramp_cap_reached`, `suppressed_recipient`). ## Full reference https://bobtailmail.com/docs