Send your first email with the API
Turn on the Developer API, verify a domain, create a sending key and make your first POST /emails call, in cURL, Node.js or Python.
You need three things to send an email with the iResendly Developer API: the API turned on for your account, a verified domain to send from, and an API key. None of them costs anything on the Free plan, and no card is needed.
1. Turn on the Developer API#
Sign in at developers.iresendly.com with your iResendly account and choose Activate Developer API. Calling the API before this returns 403 no_access.
2. Verify the domain you'll send from#
Under Domains, add your domain (or use POST /domains) and publish its three DNS records:
| Type | Name | Value |
|---|---|---|
| TXT | iresendly._domainkey | p=… (shown in the console) |
| MX | send | feedback-smtp.<region>.amazonses.com, priority 10 |
| TXT | send | v=spf1 include:amazonses.com ~all |
Choose Verify; pending domains are also re-checked automatically, and DNS can take up to 48 hours to spread. Domains you've already verified for iResendly Marketing or Business Email appear here as verified, with nothing to add. You can send from the verified domain or any subdomain of it.
3. Create a sending key#
Under API Keys, create a key with Sending access. It can only call POST /emails and POST /emails/batch, so if it ever leaks, the damage is limited. You can also restrict it to chosen domains. The full key starts with irs_ and is shown once.
- Store it in your server's environment, for example as
IRESENDLY_API_KEY, never in source control. - Call the API from your server only. Requests from browsers are blocked, so a key can't be lifted from your website's code.
- Send it as
Authorization: Bearer irs_…. Thex-api-keyheader works too.
4. Send the email#
curl -X POST 'https://api.iresendly.com/emails' \
-H 'Authorization: Bearer irs_xxxxxxxxx' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: welcome-user-8812' \
-d '{
"from": "Acme <hello@acme.com>",
"to": ["jane@example.com"],
"subject": "Welcome to Acme",
"html": "<p>Thanks for signing up, Jane.</p>",
"text": "Thanks for signing up, Jane.",
"tags": [{ "name": "category", "value": "welcome" }]
}'A 200 response with an id means the email was accepted. It's usually delivered in seconds. Open Emails in the console to follow its delivery journey, or fetch it with GET /emails/{id} using a full-access key.
A few details in that example are worth keeping in your real code:
- Both `html` and `text`. A plain-text version helps readers whose mail apps don't show HTML.
- `tags` (up to 10
{ name, value }pairs) let you find emails later, and they come back in webhook events. - `Idempotency-Key` built from something unique, such as the user's id, means a retried request never sends twice.
If it doesn't work#
Every error has the same shape, with a statusCode, a stable name to branch on, and a message that says what to fix:
| Status | name | Usual cause |
|---|---|---|
| 401 | missing_api_key | The Authorization header is missing. |
| 403 | invalid_api_key | The key is mistyped or was revoked. |
| 401 | restricted_api_key | A sending key used another endpoint, or a domain it isn't allowed. |
| 403 | domain_not_verified | The from domain isn't verified on your account yet. |
| 422 | validation_error | A field is missing or invalid; the message names it. |
| 422 | invalid_from_address | from isn't a valid address. |
Free plan limits#
The Free plan includes 3,000 emails a month and 100 a day, 1 domain and 2 requests a second. Each recipient counts as one email, across to, cc and bcc.