Send Emails

This page explains how to send emails using the Console API. Before getting started, make sure to set up a project and familiarize yourself with the Console API.

Sending Emails

Endpoint:
POST /api/console/sends

Request:

type Request = SendRequest;

This is an SendRequest object, which is used to define the email you want to send.

interface SendRequest {
	// The email address of the sender (required)
	// the domain of the email address must be verified
	from: Address;

	// The email address of the recipient (required)
	to: Address;

	// The subject of the email
	subject?: string;

	// The body of the email in HTML format
	// required if body_text is not provided
	body_html?: string;

	// The body of the email in plain text format
	// required if body_html is not provided
	body_text?: string;

	// additional headers
	headers?: Record<string, string>;

	attachments?: Attachment[];
}
	
type Address = string | {
	name?: string;
	email: string;
};

type Attachment = {
	content: string; // base64 encoded
	name?: string;
	content_type?: string; // MIME type
};
{
	// email address with a name
	"from": {
		"name": "HYVOR",
		"email": "[email protected]"
	},

	// email address without a name
	"to": "[email protected]",

	"subject": "Welcome to HYVOR",
	"body_html": "<h1>Welcome to HYVOR</h1><p>Thank you for signing up!</p>",
	"body_text": "Welcome to HYVOR\n\nThank you for signing up!",

	"headers": {
		"X-Custom-Header": "Custom Value"
	},

	"attachments": [
		{
			"content": "SFlWT1IgUm9ja3Mh",
			"name": "hello.txt",
			"content_type": "text/plain"
		}
	]
}

Retrying Failed Requests & Idempotency

Implement retrying

The HTTP request to send an email may fail due to network issues or other temporary problems. To prevent losing emails, we recommend configuring your application to retry automatically if the API returns a non-2xx status code with incremental backoff.

The recommended retry strategy is to send emails asynchronously and retry up to 3 times with an exponential backoff strategy (e.g., 30s, 2m, 5m). If the request fails after 3 retries, you can log the error and notify your team to investigate the issue.

If your setup sends emails synchronously (ex: within a web request), you can still implement retrying with a smaller timeouts, such as 1s, 2s, and 5s.

Idempotency

When retrying it is possible that your request was already accepted and queued by the API, but the response was not received by your application due to a network issue. To prevent sending the same email multiple times, you can use the X-Idempotency-Key header in your request. This header should contain a unique idempotency key for each email you send.

Some idempotency key examples:

  • welcome-email-{userId}
    (since the welcome email is sent only once to a user)
  • order-confirmation-{orderId}
    (since the order confirmation email is sent only once for an order). Note that you should use a new key if you have a "resend" option for an email.

Idempotency keys are saved for 24 hours. If you retry a request with the same idempotency key before the 24-hour period ends, the API will return the same response as the first request without actually processing it. If the idempotency key is not found, the API will process the request as usual and return a new response.

X-Idempotency-Short-Circuit header is set to true if the response was created using a previously processed request with the same idempotency key.

Response Status Codes

Code
Description
What to do
200
Email sent queued.
No action needed.
4xx
Client/request error.
Correct the request and retry with a new idempotency key.
429
Too Many Requests.
Retry after the specified Retry-After header value. If you are using an idempotency key, you can retry with the same key.
5xx
Server error.
Retry the request with the same idempotency key after a short delay.

If the server returns a 5xx status code, idempotency keys are not saved, and retrying the request is recommended. For 4xx status codes, except 429, the idempotency key is saved, and retrying the request will not have any effect unless you change the request and use a new idempotency key.

Send Status

Send status, as in the Console API Send Object, can be one of the following:

  • queued - Hyvor Relay has accepted the request and queued the email for sending. It can also mean that the email is re-queued after a temporary failure.
  • accepted - The recipient's email server has accepted the email. The status can still change to bounced or complained later.
  • bounced - The recipient's email server has rejected the email with a permanent error. The email will not be retried.
  • complained - The recipient has marked the email as spam or complained about it, usually after the email was delivered.

See Webhook Send Events for more information on each status.

Rate Limiting

TODO

Other Limits

  • Total email size is limited to 10MB
    (including headers, body, and attachments).
  • HTML body size is limited to 2MB.
  • Plain text body size is limited to 2MB.
  • Subject is limited to 998 characters.
  • Attachments are limited to 10 per email. There is no size limit for each attachment, but the total email size must not exceed 10MB.