Request
Response
Authentication, limits, and quota are checked before the stream opens, so a rejected request is an ordinary JSON error with a 4xx status. Once accepted you getContent-Type: text/event-stream and these events:
Exactly one
result or one error arrives, then the stream closes.
The result event
html and mjml depend on format
html and mjml depend on format
html is present when format is html or both; mjml when it’s mjml or both. Ask for both if you want to store the editable source alongside what you send.Reading score
Reading score
composite is the overall quality score, 0–100, and structural and content are its two main parts. dimensions holds each measured dimension by name, and which ones appear can vary. visual and branding are always null today; they stay in the shape for compatibility. Scoring also runs on a timeout, and if it doesn’t finish, score itself is null. A missing score isn’t a bad score, so never treat null as 0.subject_variants are for A/B testing
subject_variants are for A/B testing
The first entry matches the top-level
subject and preheader. The others are alternatives, some carrying a predicted open-rate bucket and a suggested split.The email is saved in your workspace
The email is saved in your workspace
email_id refers to a real email in AlpacaRelay, not just a response identifier. You can open and keep editing it in the app.Try it with curl
Node example
The stream is plain text, so no SSE library is needed — but you do have to buffer, because an event can arrive split across chunks:Set a client timeout of at least six minutes. Generation usually takes one to three, but the server’s own backstop fires later. Disconnecting doesn’t stop the generation: it still finishes, is charged, and is saved in your workspace. You just don’t receive it on the stream.
What to expect
- Generation takes roughly 1–3 minutes. Treat it as a background job, not a request you block a user on.
- A credit is taken when generation starts, and refunded if the generation itself fails. See Credits and limits.
- Three concurrent generations per workspace, and 60 calls a minute per key. Going over either one is rejected with
rate_limitedbefore the stream opens.
Next
Errors
Every code the endpoint can return, and what to do about each.
Credits and limits
What a generation costs and how much you can run at once.