Send your first email
transactional email · send email API · POST /sending/emails · emails:send · order confirmation · password reset email · quickstart · Suppressed · sending.no_verified_sender
A transactional email is one your own system asks for, about the person’s own account or order: an order confirmation, an access code, a password link. Azimea queues it, sends it from your domain and tells you what happened to it.
Before you start
Section titled “Before you start”- A verified sending domain. Your emails go out from your company’s default sender, on a domain you have verified in Settings › Sending domains (see sending and deliverability). Without one, the email is accepted but waits in the queue — it is retried every few minutes and goes out as soon as a domain is verified.
- An API key with the
emails:sendpermission, made in Settings › API keys (API keys, responses and limits). To try things without reaching anyone, make the key in a sandbox: its emails land in the sandbox’s inbox.
Send it
Section titled “Send it”POST /sending/emails takes three fields: to (one address), subject (up
to 300 characters) and html (up to 500,000 characters).
curl https://dashboard.azimea.com/api/v1/sending/emails \ -H "Authorization: Bearer $AZIMEA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to": "ana@example.com", "subject": "Your order 1042 is confirmed", "html": "<p>Hi Ana,</p><p>Thank you for your order 1042. We will let you know when it ships.</p>" }'using System.Net.Http.Headers;using System.Net.Http.Json;
using var http = new HttpClient { BaseAddress = new Uri("https://dashboard.azimea.com/api/v1/") };http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AZIMEA_API_KEY"));
var response = await http.PostAsJsonAsync("sending/emails", new{ to = "ana@example.com", subject = "Your order 1042 is confirmed", html = "<p>Hi Ana,</p><p>Thank you for your order 1042. We will let you know when it ships.</p>"});var body = await response.Content.ReadAsStringAsync();const response = await fetch('https://dashboard.azimea.com/api/v1/sending/emails', { method: 'POST', headers: { Authorization: `Bearer ${process.env.AZIMEA_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ to: 'ana@example.com', subject: 'Your order 1042 is confirmed', html: '<p>Hi Ana,</p><p>Thank you for your order 1042. We will let you know when it ships.</p>', }),});const body = await response.json();$ch = curl_init('https://dashboard.azimea.com/api/v1/sending/emails');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('AZIMEA_API_KEY'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'to' => 'ana@example.com', 'subject' => 'Your order 1042 is confirmed', 'html' => '<p>Hi Ana,</p><p>Thank you for your order 1042. We will let you know when it ships.</p>', ]), CURLOPT_RETURNTRANSFER => true,]);$body = json_decode(curl_exec($ch), true);import os, requests
response = requests.post( "https://dashboard.azimea.com/api/v1/sending/emails", headers={"Authorization": f"Bearer {os.environ['AZIMEA_API_KEY']}"}, json={ "to": "ana@example.com", "subject": "Your order 1042 is confirmed", "html": "<p>Hi Ana,</p><p>Thank you for your order 1042. We will let you know when it ships.</p>", },)body = response.json()Read the answer
Section titled “Read the answer”{ "isSuccess": true, "value": { "id": "01a10900-0000-7000-8000-000000000301", "status": "Queued", "reason": null }, "status": 0, "errors": [], "fieldErrors": null}idis the email’s id. Keep it: the delivery webhooks carry it asmessage_id.statusisQueued— accepted, it goes out within seconds — orSuppressed: stopped before sending.reasonsays why an email was stopped. It starts with the reason’s code (sending.gate_bounced), followed by detail separated by|: read it up to the first|.
A transactional email needs no marketing consent, so the sending gate stops it only for an address that no longer works or that complained:
reason starts with |
What it means | What you do |
|---|---|---|
sending.gate_bounced |
The address permanently refused your emails. | Ask the person for another address. |
sending.gate_complained |
The person marked one of your emails as spam. | Nothing: Azimea will not write to them again. |
After it is queued, the email moves through the email statuses: Sent, then Delivered
or Bounced.
Transactional, not marketing
Section titled “Transactional, not marketing”Use this call only for messages about the person’s own account or order. Newsletters, offers and reminders to buy are marketing: send them as campaigns or flows, which check each person’s consent before sending. A transactional email carries no unsubscribe footer, because there is nothing to unsubscribe from; its links and opens are tracked like any other email’s.
Make retries safe
Section titled “Make retries safe”Send an Idempotency-Key header with your own id for this email (an order number, a UUID): up to 150 visible ASCII
characters, no spaces. If the call times out and you send it again with the same key, Azimea returns the first message
and sends nothing more. The key holds for your whole account, whichever API key sends it, and a second call with the same
key returns the first message even if its body differs.
curl https://dashboard.azimea.com/api/v1/sending/emails \ -H "Authorization: Bearer $AZIMEA_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: order-1001-confirmation" \ -d '{"to": "ana@example.com", "subject": "Your order 1001", "html": "<p>Thanks for your order.</p>"}'Without the header, each call queues a new email, and a retry after a timeout can send it twice. More in retries.
- Hear back about delivery, bounces and clicks: webhooks.
- Every field and answer:
POST /sending/emailsin the reference.