Guides

Sending email

Transactional email is the mail your application sends one person because of something they did: a receipt, a sign-in link, an order update. It has its own key, its own limits and no unsubscribe link.

Before the first send

  • A domain on your account that is set up for sending. Add it in the console under Domains; the records are set up with you, and the domain is ready once they are seen.
  • A key with the mail:send scope. Keep it to that scope alone unless the same system needs more.

The from address must be on one of those domains. A domain that is not on the account is answered 400; one that is not ready yet, 409 conflict.

POST/emails

Send an email

Sends one transactional email: a message your application sends one person because of something they did, such as a receipt, a sign-in link or an order update. It carries no unsubscribe link, so the rules are strict. An address that bounced or marked your mail as spam is never sent to. Someone who unsubscribed may still get account, security, receipt and order mail, but never a notification, and never a message that reads as selling; that is refused with the words that gave it away. Refusals answer 409 and are listed in GET /emails. The from address must be on one of your domains that is set up for sending (400 if the domain is not yours, 409 if it is not ready, 409 if sending is stopped for the account). One address gets at most 20 messages a day, and the account has an hourly limit by plan; either answers 429. Give text, html or both; without text, a plain text part is made from the HTML. Send an idempotencyKey to make retries safe: the same key returns the first message with "repeated": true instead of sending again. The message body is not kept, only who, when, the subject and the outcome. Needs a key holding mail:send.

Needsmail:sendReturns200 OK

Body

fromstring (email)required
The sender. Its domain must be one of yours, verified and set up for sending.
fromNamestringoptional
A display name for the sender, up to 120 characters.
tostring (email)required
The one recipient.
replyTostring (email)optional
Where replies go.
subjectstringrequired
1 to 300 characters.
textstringoptional
The plain text part, up to 200,000 characters. Give text, html or both.
htmlstringoptional
The HTML part, up to 500,000 characters.
category'account' | 'security' | 'receipt' | 'order' | 'notification'required
What kind of message this is. Only account, security, receipt and order mail may reach someone who unsubscribed.
idempotencyKeystringoptional
Up to 200 characters. A retry with the same key returns the first message and sends nothing.
POST/emails
curl -X POST https://app.rykonmail.com/api/v1/emails \
  -H "Authorization: Bearer $RYKON_MAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "orders@northwind-local.test",
    "fromName": "Northwind Traders",
    "to": "jamie.chen@example.com",
    "replyTo": "help@northwind-local.test",
    "subject": "Your receipt for order 10482",
    "text": "Thanks for your order.\n\nOrder 10482: 2 x Linen apron, $48.00.\nTotal paid: $48.00.",
    "html": "<p>Thanks for your order.</p><p>Order 10482: 2 x Linen apron, $48.00.<br>Total paid: <strong>$48.00</strong>.</p>",
    "category": "receipt",
    "idempotencyKey": "order-10482-receipt"
  }'
Response
200 OK
{
  "id": "682e5ffd-1528-4b9e-9b81-65903d3d9593",
  "category": "receipt",
  "from": "orders@northwind-local.test",
  "to": "jamie.chen@example.com",
  "subject": "Your receipt for order 10482",
  "state": "sent",
  "messageId": "simulated-fa61a1bd-2389-4b00-ab0c-63ac54867b0c",
  "error": null,
  "createdAt": "2026-10-30T06:18:05.177Z"
}

In the reference: Send an email

Categories

Every message names its category. It is how a person who unsubscribed from your marketing still gets the mail they cannot do without, and only that.

categoryForAfter unsubscribing
accountSign-up confirmations, email changes, account noticesStill delivered
securitySign-in links, password resets, new device alertsStill delivered
receiptReceipts and invoicesStill delivered
orderOrder, shipping and booking updatesStill delivered
notificationActivity notifications: a comment, a mention, a digestNot sent

Who may receive what

Transactional mail skips consent, which would make it the easy way around it. So the rules are firm, and a message that breaks one is refused, never queued:

  • An address that bounced or marked your mail as spam is never sent to, whatever the category.
  • Someone who unsubscribed gets account, security, receipt and order mail only, and not if it reads as selling. The refusal names the words that made it read that way.
  • One address gets at most 20 transactional messages a day.

A refusal is answered 409 refused with the reason. Do not retry it; see Errors.

Idempotency

Give each message an idempotencyKey that is unique to it in your system, such as order-1042-receipt. If your request times out, send it again with the same key: the first message is returned, marked "repeated": true, and nothing is sent twice. If we could not hand the message over at all, a retry with the same key sends it.

Content

  • Give text, html or both. When you give only HTML, a readable text part is made from it for the clients and filters that want one.
  • No unsubscribe link is added: nobody can opt out of their own password reset. Do not put marketing in a transactional message; send it as a campaign.
  • The body is not stored. The log keeps who, when, the subject and the outcome, and you can read it in the console under Sending.

Your own reputation

Your mail is sent under your account's own sending identity, with its own bounce and complaint rates. Nobody else's mistakes can land your receipts in spam.
GET/emails

List sent emails

The 100 most recent transactional messages, newest first, including the ones that were refused and why. With them: how many were sent in the last hour and day, how many were refused today, the account's hourly limit and the most one address may get in a day. Bodies are never kept, so they are not here. Needs sending:read.

Needssending:readReturns200 OK

Query parameters

tostring (email)optional
Only messages to this address.
state'sent' | 'refused' | 'failed'optional
Only messages in this state.
GET/emails
curl "https://app.rykonmail.com/api/v1/emails?to=jamie.chen%40example.com" \
  -H "Authorization: Bearer $RYKON_MAIL_KEY"
Response
200 OK
{
  "messages": [
    {
      "id": "ba525624-1079-436d-9525-88eb1b013547",
      "category": "order",
      "from": "orders@northwind-local.test",
      "to": "jamie.chen@example.com",
      "subject": "20% off everything this weekend",
      "state": "refused",
      "messageId": null,
      "error": "jamie.chen@example.com unsubscribed and this reads as marketing (% off, shop now); transactional mail must not sell",
      "createdAt": "2026-10-30T06:18:05.232Z"
    },
    {
      "id": "682e5ffd-1528-4b9e-9b81-65903d3d9593",
      "category": "receipt",
      "from": "orders@northwind-local.test",
      "to": "jamie.chen@example.com",
      "subject": "Your receipt for order 10482",
      "state": "sent",
      "messageId": "simulated-fa61a1bd-2389-4b00-ab0c-63ac54867b0c",
      "error": null,
      "createdAt": "2026-10-30T06:18:05.177Z"
    }
  ],
  "lastHour": 1,
  "lastDay": 27,
  "refusedToday": 25,
  "hourlyLimit": 2000,
  "perRecipientPerDay": 20
}

In the reference: List sent emails