# Email

Send transactional email from your app with one API call, from a CloudHike.dev address or your own domain.

## How it works

Tick the box to accept the email acceptable use policy (https://cloudhike.dev/legal/email-policy) and click Deploy on the Email card. You get `EMAIL_API_URL` and `EMAIL_API_KEY`. Keep the key on your server: anyone with it can send as your project.

- Mail goes out from `<project>@cloudhike.dev` with no setup, or from any address on a domain you verify.
- Transactional email only: sign-in links, password resets, receipts, alerts. No marketing or bulk mail.
- Message bodies are never stored. The Logs tab shows who each message went to and what happened.

## Send an email

*From your server*

```ts
const res = await fetch(`${process.env.EMAIL_API_URL}/send`, {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "x-api-key": process.env.EMAIL_API_KEY!,
  },
  body: JSON.stringify({
    to: "customer@example.com",
    subject: "Your receipt",
    html: "<p>Thanks for your order.</p>",
    text: "Thanks for your order.",
    from: "receipts@acme.com",   // optional, needs acme.com verified
    fromName: "Acme",
    replyTo: "support@acme.com",
  }),
});
const { results } = await res.json(); // [{ to, id, status }]
```

| Field | Meaning |
| --- | --- |
| `to` | One address or an array. Each recipient counts as one email. |
| `subject` | Up to 200 characters, no line breaks. |
| `html`, `text` | Send either or both, up to 256 KB each. |
| `from` | Any address on one of the project's verified domains. Left out, mail goes from `<project>@cloudhike.dev`. |
| `fromName` | Display name, 1 to 60 characters, with no address or link in it. |
| `replyTo` | Where replies go. Set it when sending from cloudhike.dev. |
| `scheduledAt` | ISO time up to 7 days ahead. Answers 202; cancel with `POST {EMAIL_API_URL}/emails/<id>/cancel`. |

## Send from your own domain

1. Open the project's Email page, go to Domains and add your domain. A subdomain such as `mail.acme.com` keeps email reputation apart from your main domain.
2. Add the records it lists at your DNS provider: three DKIM CNAME records (required), an MX and an SPF TXT record on `bounce.<domain>`, and a DMARC TXT record (recommended).
3. Click Verify now, or wait: we check every few minutes for 72 hours. Each record shows whether it was found.
4. Once the domain shows Verified, send with `from` set to any address on it.

> **Note:** Free accounts can add 1 domain and Pro accounts 5, across all projects. If the DKIM records are removed later, the domain is marked failed and sending from it stops until you verify it again.

## Limits

|  | Free | Pro |
| --- | --- | --- |
| Emails per 24 hours | 100 | No limit |
| Emails per month | 3,000 | No limit |
| Price | Free | 3,000 a month per project included, then $0.40 per 1,000 |
| Emails per minute | 10 | 300 |
| Recipients per request | 3 | 50 |
| Custom domains | 1 | 5 |

- Over a limit the API answers 429 with a `Retry-After` header.
- Each recipient counts as one email. On Pro, emails sent above the allowance are charged from your credits every hour; refused, failed and cancelled messages are free. A monthly spend cap under Settings limits what you can spend.
- Addresses that bounce for good or report spam are never mailed again.
- Sending pauses for a project whose mail bounces 8% or is reported as spam 0.3% of the time over 7 days.
- The Overview tab charts each day's delivered, bounced and failed mail and your bounce and complaint rates.

## Use with AI

Let your coding agent send your app's transactional email.

```text
Read https://cloudhike.dev/docs/md/email. Send this app's transactional email (sign-in links, password resets, receipts) through CloudHike.dev: call EMAIL_API_URL/send with EMAIL_API_KEY from server code only, set replyTo, and handle 429 responses.
```
