react-email
Hail doesn't render React or store templates — you render a
react-email component to a string and send that
string. The body goes out exactly as given: a full
<!DOCTYPE html>…</html> document passes through unchanged.
Render the template
npm install react-email react react-dom -E// Welcome.tsx
import * as React from "react";
import { Html, Body, Text, Button } from "react-email";
export function Welcome({ name }: { name: string }) {
return (
<Html lang="en">
<Body>
<Text>Hi {name}, welcome aboard.</Text>
<Button href="https://example.com/start">Get started</Button>
</Body>
</Html>
);
}render() is async — it returns a Promise<string>. Call it twice: once for
the HTML body, once with { plainText: true } for the text body.
Send it (Node)
// send.tsx
import * as React from "react";
import { render } from "react-email";
import { Welcome } from "./Welcome";
const html = await render(<Welcome name="Ada" />);
const text = await render(<Welcome name="Ada" />, { plainText: true });
const res = await fetch(`${process.env.HAIL_API_URL}/v1/emails`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HAIL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
to: ["ada@example.com"],
from: "onboarding@yourdomain.com",
subject: "Welcome aboard",
body_html: html,
body_text: text,
recipient_consent: true,
}),
});Run it with tsx (npm install -D tsx; needs "type": "module" in package.json):
npx tsx send.tsxSend it (Python SDK)
There is no JS/TS SDK. Render in Node — at build time, or in a small script —
write the output to a file, and send the string with
hail-sdk:
from pathlib import Path
from hail import Client
html = Path("welcome.html").read_text()
async with Client() as client: # reads HAIL_API_KEY / HAIL_API_URL from env
await client.emails.create(
to=["ada@example.com"],
from_="onboarding@yourdomain.com",
subject="Welcome aboard",
body_html=html,
recipient_consent=True,
)Notes
- Field names are
body_html/body_text.EmailCreateinopenapi/openapi.yamlforbids extra fields —html/textreturn422. - Open and click tracking only work with an HTML body. A plain-text-only email still sends, but opens and clicks are never tracked.
- Hail adds nothing to the body — no footer, no tracking notice. Disclose AI use yourself where the law requires it.
- An email with attachments goes out as raw MIME
(
core/hailhq/core/providers/email/ses.py), which adds one trailing line break to each text part — no visible effect.
Webhooks
When a subscribed event occurs — inbound mail or SMS, a delivery report, a call outcome — Hail POSTs a signed JSON event to your URL. Verify the X-Hail-Signature header against the once-shown secret. Return any 2xx, and you are done. Hail retries a non-2xx response (or a timeout) on a fixed ladder.
API versioning
/v1/<resource> is the canonical, documented form of every customer-facing Hail API route. It appears in the OpenAPI spec (openapi/openapi.yaml) and is what the CLI and generated clients target.