Transactional email API
Send single, personal emails from your own application through obanox: password resets, order confirmations, invoices, account notifications.
Each request sends one email to one recipient. Emails are queued and delivered within seconds. Addresses that bounce or report your mail as spam are blocked automatically, which protects your sender reputation.
Before you start
| Where to find it | |
|---|---|
| API key and API secret | In your obanox account under Account → API. See Authentication. |
| A verified sender domain | In your account under Email delivery. Add your domain (e.g. example.com) and publish the DNS records shown. You can only send from addresses on a domain with the status verified. |
| A newsletter approved for sending | Every email is sent on behalf of one of your newsletters. It must be approved for sending, and not paused. Request approval in your account under Settings → Sending approval; we usually reply within a few hours. |
| Your newsletter's slug | See Your newsletter's slug. |
Send an email
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
API-KEY | Your API key |
API-SECRET | Your API secret |
Body fields
| Field | Type | Required | Description |
|---|---|---|---|
from | string | yes | Sender address. Must be on one of your verified sender domains, e.g. [email protected]. Max. 255 characters. |
from_name | string | no | Sender name shown in the inbox, e.g. Example Shop. Max. 255 characters, single line. |
to | string | yes | Recipient address. Exactly one recipient. Max. 255 characters. |
reply_to | string | no | Address that replies go to. Max. 255 characters. |
subject | string | yes | Subject line. Max. 998 characters, single line. |
html | string | one of html / text | HTML body. |
text | string | one of html / text | Plain-text body. |
{
"from": "[email protected]",
"from_name": "Example Shop",
"to": "[email protected]",
"reply_to": "[email protected]",
"subject": "Your order #10023",
"html": "<p>Hello Max,</p><p>thank you for your order.</p>",
"text": "Hello Max,\n\nthank you for your order."
}
The whole request may be at most 512 KB. We recommend sending both html and text: many mail programs and spam filters prefer messages with a plain-text version.
Response
202 Accepted: the email was accepted and queued for delivery.
{
"id": 4711,
"status": "queued"
}
Store the id if you want to reference the email when contacting support.
If you turned on Approve transactional emails before sending in your settings, the status is awaiting_approval instead: the email is only sent once you approve it under Transactional emails. The same applies to emails sent over SMTP when approval is on for SMTP.
Examples
curl -X POST "https://obanox.com/api/v1/my-newsletter/send" \
-H "Content-Type: application/json" \
-H "API-KEY: your-api-key" \
-H "API-SECRET: your-api-secret" \
-d '{
"from": "[email protected]",
"from_name": "Example Shop",
"to": "[email protected]",
"reply_to": "[email protected]",
"subject": "Your order #10023",
"html": "<p>Hello Max,</p><p>thank you for your order.</p>",
"text": "Hello Max,\n\nthank you for your order."
}'
<?php
$payload = [
'from' => '[email protected]',
'from_name' => 'Example Shop',
'to' => '[email protected]',
'subject' => 'Your order #10023',
'html' => '<p>Hello Max,</p><p>thank you for your order.</p>',
'text' => "Hello Max,\n\nthank you for your order.",
];
$ch = curl_init('https://obanox.com/api/v1/my-newsletter/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'API-KEY: ' . getenv('OBANOX_API_KEY'),
'API-SECRET: ' . getenv('OBANOX_API_SECRET'),
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status !== 202) {
$error = json_decode($body, true)['error'] ?? $body;
// handle the error, see "Errors"
}
const response = await fetch('https://obanox.com/api/v1/my-newsletter/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'API-KEY': process.env.OBANOX_API_KEY,
'API-SECRET': process.env.OBANOX_API_SECRET,
},
body: JSON.stringify({
from: '[email protected]',
from_name: 'Example Shop',
to: '[email protected]',
subject: 'Your order #10023',
html: '<p>Hello Max,</p><p>thank you for your order.</p>',
text: 'Hello Max,\n\nthank you for your order.',
}),
});
if (response.status !== 202) {
const { error } = await response.json();
// handle the error, see "Errors"
}
import os
import requests
response = requests.post(
"https://obanox.com/api/v1/my-newsletter/send",
headers={
"API-KEY": os.environ["OBANOX_API_KEY"],
"API-SECRET": os.environ["OBANOX_API_SECRET"],
},
json={
"from": "[email protected]",
"from_name": "Example Shop",
"to": "[email protected]",
"subject": "Your order #10023",
"html": "<p>Hello Max,</p><p>thank you for your order.</p>",
"text": "Hello Max,\n\nthank you for your order.",
},
timeout=10,
)
if response.status_code != 202:
error = response.json().get("error")
# handle the error, see "Errors"
Errors
Errors return a JSON body with an error message:
{ "error": "The from address is not on a verified sender domain." }
| Status | error | What it means | What to do |
|---|---|---|---|
401 | Invalid api-key or api-secret. | Headers missing or wrong. | Check your credentials. Send them as API-KEY / API-SECRET (with a hyphen). |
403 | Access to this list denied. | The slug doesn't exist or belongs to another account. | Check the slug. |
413 | The request is too large. | The body is over 512 KB. | Make the email smaller, e.g. link to images instead of embedding them. |
422 | The body must be a JSON object. | The body isn't valid JSON. | Send a JSON object with Content-Type: application/json. |
422 | Missing or invalid fields: … | The listed fields are missing, invalid, too long or contain line breaks. | Fix the listed fields. |
422 | The from address is not on a verified sender domain. | The from domain isn't verified in your account. | Verify the domain, or use an address on a verified one. |
422 | The list is not approved for sending or sending is paused. | The newsletter isn't approved yet, or sending was paused (e.g. too many bounces or spam complaints). | Not approved yet: request approval under Settings → Sending approval. Paused: contact obanox support. |
422 | Your account has more subscribers than your plan allows. … | Your plan's subscriber limit is exceeded. | Upgrade your plan. |
422 | recipient_suppressed | The recipient is blocked because an earlier email bounced or was marked as spam (see below). | Don't retry right away. Ask the recipient for a different address; a block after an undeliverable email ends after 7 days. |
429 | The daily email limit of your plan is reached. | Your plan's daily email limit is used up. | Try again tomorrow, or upgrade your plan. |
5xx | – | Temporary problem on our side. | Retry after a short wait (e.g. 1 min, then 5 min). |
Only retry on 429 (the next day) and 5xx. A 4xx error won't succeed by repeating the same request.
Send over SMTP
If your application, shop or CMS can only send email over SMTP, use the obanox SMTP server instead of the HTTP API. It uses the same API key and secret, the same verified sender domains and the same limits. Unlike the API, SMTP also supports attachments, Cc and Bcc.
| Server | smtp.obanox.com |
|---|---|
| Port and encryption | 587 with STARTTLS (recommended), or 465 with SSL/TLS |
| Authentication | PLAIN or LOGIN (usually just "on" in your SMTP settings) |
| Username | my-newsletter:{your API key}, your newsletter's slug and API key joined by a colon |
| Password | Your API secret |
The From address of each email must be on a verified sender domain. Every recipient (To, Cc and Bcc) counts as one email and appears as its own entry under Transactional emails. Bcc recipients stay hidden from the others.
The server answers with standard SMTP codes, so your application can tell a permanent error from a temporary one:
| Reply | What it means | What to do |
|---|---|---|
250 | Accepted and queued. | – |
535 | Username or password wrong, or the slug belongs to another account. | Check the username format and your API secret. |
530 | Not logged in. | Turn on SMTP authentication. |
454 | Login temporarily not possible (problem on our side). | Your SMTP client retries automatically. |
550 | The email was refused, with the same reason as the matching API error (unverified sender, list not approved, recipient blocked, too large, …). | Fix the cause; resending the same email won't help. |
452 | More than 50 recipients in one email. | Your SMTP client sends the remaining recipients in another email automatically. |
450 | Temporary: daily limit reached or a problem on our side. | Your SMTP client retries automatically. |
Delivery
- Asynchronous:
202means the email was accepted, not yet delivered. It normally goes out within a few seconds. - Temporary problems at the recipient's side (e.g. their mail server is briefly unavailable) are retried automatically. You don't need to resend.
- If an accepted email can't be sent on our side, it is kept and can be resent by obanox support. Don't send it again yourself, or the recipient may get it twice.
- Counted towards your plan: every transactional email counts towards your plan's daily email limit, together with your newsletter emails. An email counts once, on the day it is accepted: also while it awaits your approval and if you reject it, but not again when you approve it later.
Bounces and spam complaints
To protect your sender reputation, obanox blocks addresses automatically:
| Event | Blocked for |
|---|---|
| Hard bounce: the address doesn't exist or permanently rejects mail | The newsletter the email was sent through |
| Spam complaint: the recipient marked an email as spam | The newsletter the email was sent through |
| Undeliverable: the recipient's mailbox is full, or delivery was retried for hours and gave up, e.g. because the recipient's domain doesn't resolve. This also applies when it happens to one of your newsletter emails | The newsletter the email was sent through, for 7 days |
| Soft bounce: other temporary problems, e.g. an auto-reply | Not blocked |
This also covers your newsletter emails: an address that hard-bounced on a newsletter issue can't receive transactional emails from your account either.
A request to a blocked address returns 422 recipient_suppressed. Blocks after an undeliverable email end on their own after 7 days. If an address was blocked by mistake (for example, the recipient has since fixed their mailbox), you can remove it under Suppressed emails in your account.
A high bounce or complaint rate can pause your newsletter's sending, which also stops the API (422 … sending is paused). Keep your rates low by only emailing addresses that recently gave them to you, and removing addresses that return recipient_suppressed.
Good practice
- One request per recipient. To email several people, send several requests.
- Use a dedicated sender address, e.g.
[email protected]or[email protected], and setreply_toif recipients should be able to answer. - Transactional emails only. Use this API for emails a recipient triggered or expects (account, order, security). Send marketing and newsletters through your newsletter, so recipients can unsubscribe.
- Avoid duplicate sends. If your request times out, you can't tell whether the email was accepted. Retrying may send it twice, so for critical emails log the request before retrying.
Limits
| Recipients per request | 1 (API), 50 per email (SMTP) |
|---|---|
| Request size | 512 KB (API), 10 MB per email incl. attachments (SMTP) |
| Attachments | Not supported over the API; supported over SMTP |
| Daily emails | According to your plan |
| Sender | Addresses on your verified sender domains only |
Support
Questions or an address to unblock? Contact obanox support and include the email id from the API response.