Skip to content
Coritan Docs

Send email over HTTPS

Send a test message from the Send tab, then send from your application with the send API and an API key.

View as Markdown

In the dashboard

The send API takes a message as JSON over HTTPS and hands it to SMTP Relay, which signs it for your domain and delivers it as it does mail sent over SMTP. Use it where an SMTP connection is awkward, such as in a serverless function. Before you wire up an application, you can check a domain end to end by sending a test message from the Send tab.

  • A verified sending domain on the relay. Over SMTP a domain can send once its ownership check passes, but the send API waits until the domain shows Verified. See Add a sending domain to SMTP Relay.
  • At least one SMTP credential on the relay. The send API submits each message with one: a credential on the From address's domain when there is one, otherwise any active credential on the relay.
  • A send API key for the application. The Send tab does not need one.

Send a test message from the dashboard

Section titled Send a test message from the dashboard
  1. In the dashboard, go to Email, open the SMTP Relay service, then the Send tab.
  2. In From, enter the part of the address before the @, such as no-reply, and choose a verified domain after it.
  3. Optionally, enter a From name, such as Example Billing.
  4. In To, enter up to 50 addresses, separated by commas or spaces.
  5. Enter a Subject and a Message. The message is plain text.
  6. In Category, leave Service default or choose Transactional or Marketing. See Transactional and marketing mail.
  7. Select Send message.

A toast says Accepted for 1 recipient., and a green Accepted for delivery box links to the Events tab, where you can watch the message arrive. The test message counts towards the month's allowance like any other. When the relay refuses the message, a Could not send the message box shows one of the messages in Troubleshooting.

Post the message to /mail/send with the key in the X-Api-Key header:

Shell
curl -X POST https://api.coritan.com/api/v1/mail/send \
  -H "X-Api-Key: $MAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "receipts@example.com",
    "from_name": "Example Billing",
    "to": ["alex@example.com"],
    "subject": "Your receipt",
    "text": "Thanks for your order.",
    "html": "<p>Thanks for your order.</p>",
    "category": "transactional"
  }'

The dashboard's API keys tab shows the same endpoint on www.coritan.com. Both hosts answer it.

The body takes these fields. Only from, to and one of text or html are needed:

from
The sender's address, 3–320 characters, on a verified domain of the relay. It is used as the envelope sender too. from_address is accepted as another name for it.
from_name
Optional, up to 255 characters. The name shown next to the address.
to
A list of 1–50 addresses.
cc
Optional, a list of up to 50 addresses. A transactional message takes 50 recipients across to and cc together.
subject
Optional, up to 998 characters. Empty when left out.
text
The plain-text body, up to 5,000,000 characters.
html
The HTML body, up to 10,000,000 characters. With text as well, the message carries both and the recipient's app picks one.
reply_to
Optional, up to 320 characters. The address replies go to.
headers
Optional, an object of extra headers, such as {"X-Order-Id": "10492"}. Only headers whose names start with X-, plus List-Unsubscribe, List-Unsubscribe-Post, List-Id and Precedence, are added; any other header is dropped without an error. A name can have up to 64 characters and a value is cut at 998.
category
Optional, transactional or marketing. Left out, the message takes the relay's default category.

The send API has no field for attachments or blind copies, and it ignores fields it does not know, such as bcc or attachments. To send either, use SMTP. The whole message, as built, can be up to 25 MB.

We add Date, a Message-ID at your domain and an X-Mail-Category header that names the category we sent the message as.

The answer is 202: we accepted the message and queued it for delivery. It does not mean the message has arrived. Follow it on the Events tab or with webhooks.

A transactional message answers with the addresses we sent it to:

JSON
{
  "accepted": ["alex@example.com"],
  "suppressed": [],
  "node": "mx1.mail-fra.coritan.com",
  "message_id": "<175890432171.2481.9311874401294517206@example.com>"
}
accepted
The recipients we queued the message for.
suppressed
The recipients we left out because they are on the relay's suppression list. When every recipient is suppressed, nothing is sent, accepted is empty and node is null, and the answer is still 202.
node
The name of the mail server that took the message.
message_id
The message's Message-ID header. Webhook events and receiving servers refer to the message by it.

With "category": "marketing", or no category on a relay whose default is marketing, the send API sends each address in to and cc its own copy, addressed to that person alone. Each copy carries List-Unsubscribe and List-Unsubscribe-Post headers with a link for that recipient, so receiving apps can show an unsubscribe button. Transactional and marketing mail explains what an unsubscribe does.

The answer counts the copies and lists each one:

JSON
{
  "accepted": 2,
  "category": "marketing",
  "messages": [
    {
      "accepted": ["alex@example.com"],
      "suppressed": [],
      "node": "mx1.mail-fra.coritan.com",
      "message_id": "<175890432171.2481.9311874401294517206@example.com>"
    },
    {
      "accepted": ["sam@example.com"],
      "suppressed": [],
      "node": "mx1.mail-fra.coritan.com",
      "message_id": "<175890432172.2481.5170284763319902451@example.com>"
    }
  ]
}

Here accepted is a number, the copies we queued, where a transactional answer gives a list of addresses. A copy to a suppressed address appears in messages with an empty accepted and is not counted.

Read what the relay may still send with the same key:

Shell
curl https://api.coritan.com/api/v1/mail/send/limits \
  -H "X-Api-Key: $MAIL_API_KEY"

The answer holds the relay's allowance and hourly limit, which How SMTP Relay sending limits work describes field by field, and three more fields:

sending_frozen
true while sending is paused for the relay.
max_recipients
50, the most recipients one request can have.
max_message_bytes
26214400, the largest message the send API builds, in bytes (25 MB).

Check remaining before a large batch: it is null when the relay has no monthly cap.

401 X-Api-Key header required
The request has no X-Api-Key header. The send API does not read Authorization.
401 Invalid API key
The key is wrong or revoked, or the relay is not active. See Create and revoke send API keys.
403 API key cannot send
The key does not have the send ability. Keys you create on the API keys tab always have it, so create a new key.
422 with a detail list
A field is missing or out of range: no from or to, more than 50 addresses in to or cc, or a category other than transactional or marketing. Each item in detail names the field in loc.
400 Provide a text or html body
Add text, html or both.
400 At most 50 recipients per message
A transactional message has more than 50 addresses in to and cc together. Split it into several requests.
400 Message exceeds 25 MB
Shorten the message, or link to large content instead of putting it in the body.
400 example.org is not a domain on this service
The domain of from is not on the relay. Use an address on one of the relay's domains, or add the domain. A subdomain is a domain of its own: with only send.example.com on the relay, send from an address at send.example.com. Over SMTP, the From header can use example.com when your account also holds that domain, in Coritan DNS or on another mail service; the send API cannot.
400 example.com is not verified yet; publish its DNS records first
The domain is on the relay but not verified. Publish its records and verify it.
400 Create an SMTP credential on this service before sending through the API
The relay has no active SMTP credential. Create one, or turn one back on.
400 Sending is paused on this service; contact support
Sending is paused for the relay. See Sending reputation and deliverability.
429 Monthly allowance and its 12% buffer are used up; upgrade the plan to continue
Sending the request would take the relay past everything its plan allows this month. A free plan says Monthly sending allowance reached; upgrade the plan to continue. See How SMTP Relay sending limits work.
400 Rejected by mail engine: followed by an SMTP reply
The relay's mail server refused the message, and the reply after the colon says why. The replies it can give are listed under SMTP credentials.
400 No mail node is available right now or 400 All mail nodes refused the connection:
We could not reach a mail server to take the message. Nothing was sent, so retry the request after a short wait.
503 Mail service unavailable
The relay's service could not be found on our side. Contact support if it persists.

The Send tab posts to /client/smtp-relay/{service_id}/messages, which takes the same body and gives the same answers with an access token in place of an API key:

Shell
curl -X POST https://api.coritan.com/api/v1/client/smtp-relay/4812/messages \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"from": "no-reply@example.com", "to": ["alex@example.com"], "subject": "Test", "text": "Hello from SMTP Relay."}'

It answers 202 as above. A relay that is not active answers 409 Service is not active.

On a Mail Hosting service, POST /client/mail/{service_id}/messages answers 404 Not an SMTP Relay service. Mailboxes send through a mail app or webmail.

API operations on this page