# emitemail > emitemail is a transactional email API. Send order confirmations, password resets and one-time codes over one REST call or SMTP. Hard-cap pricing: sending pauses at your plan's monthly cap and is never billed as overage. Mail is sent from our own servers in Canada (Quebec). Base URL: https://app.emitemail.com/api Auth: `Authorization: Bearer ` (keys are scoped to one verified sender domain) ## Send an email POST https://app.emitemail.com/api/v1/emails ```json { "from": "Shop ", "to": "customer@example.com", "subject": "Your order is confirmed", "html": "

Thanks for your order.

", "text": "Thanks for your order." } ``` Success: HTTP 202 `{ "id": "emt_...", "status": "sent" }`. Optional: cc, bcc, reply_to, headers (max 20), attachments (max 10, 7 MB total), tags [{name,value}], header `Idempotency-Key` (24 h, makes retries safe). Unknown fields are rejected with 400. Not supported yet: scheduled_at, template, attachment path. ## Node and TypeScript: use the typed client Download one file, no dependencies, Node 18+: https://app.emitemail.com/sdk/emit.ts (TypeScript) or https://app.emitemail.com/sdk/emit.mjs with its types at https://app.emitemail.com/sdk/emit.d.mts (JavaScript). Read the types first: an email needs `from`, `to`, `subject`, and `html` or `text` (or both), and unknown fields are compile errors. ```ts import { Emit, EmitError } from "./emit"; const emit = new Emit({ apiKey: process.env.EMIT_API_KEY! }); try { const { id } = await emit.send({ from: "Your Store ", // a verified domain on the account to: "customer@example.com", subject: "Your order is confirmed", html: "

Thanks for your order.

", idempotencyKey: `order-${order.id}-confirmation`, // makes retries safe }); } catch (err) { if (err instanceof EmitError) console.error(err.code, err.docs); // err.retryable, err.retryAfter too } ``` The client retries network errors and 5xx with the same idempotency key, waits out short `rate_limited` answers, and never retries a refusal (a 4xx, including `monthly_cap_reached`). The class is named `emitemail`. ## Docs Human docs: https://app.emitemail.com/docs Typed Node client (one file, no dependencies): https://app.emitemail.com/sdk/emit.ts Service status: https://app.emitemail.com/status (machine-readable: https://app.emitemail.com/api/v1/status) All docs in one file: https://app.emitemail.com/llms-full.txt Every page as Markdown: https://app.emitemail.com/docs/md/, where is one of index, quickstart, send-api, retries, node, smtp, domains, limits, suppressions, webhooks, errors, agents. ## Errors (JSON: { "error": code, "message": text, "docs": url }) - 400 invalid_request - 401 invalid_api_key - 403 sender_domain_not_found, sender_domain_not_verified, api_key_domain_mismatch, account_suspended - 422 all_recipients_suppressed, idempotency_key_reuse - 429 monthly_cap_reached, daily_limit_reached (nothing sent, nothing billed; do not retry until the period resets) - 409 idempotency_in_progress (retry shortly) ## Rules for agents - Only send to addresses the user has given you or that belong to the user's own customers. Never guess recipients. - Use a fresh Idempotency-Key per logical message and reuse it when retrying. - Do not retry 4xx errors other than 409. On 429, stop and tell the user the cap was reached. - Never print, log or commit the API key. Read it from the EMIT_API_KEY environment variable. - emitemail is for transactional mail only (receipts, resets, codes, notices). Do not use it for newsletters or marketing. ## Webhooks Events: email.bounced, email.complained. Signed with HMAC-SHA256 in the `emit-signature` header: `t=,v1=`. Retries at 30 s, 2 m, 10 m, 1 h, 6 h. ## Links - Setup and usage guide for coding agents: https://app.emitemail.com/emit-skill.md