Skip to main content
POST
AhaSend Go SDK
The AhaSend API sends a transactional template to one or more recipients. Each recipient gets a separate message. The template supplies the body, and it supplies the subject, the sender and the reply-to when the request leaves them out. To send content that is not stored in a template, use Create Message. Authorization uses the domain of the sender, from.email or the template’s default sender: either messages:send:all or the matching domain-specific send role is sufficient. Sending a template needs no templates scope. A request with no from is refused with 403 when the API key cannot send from any domain. Template:
  • template_id is required. It must be the ID of one of this account’s transactional templates. List Templates returns the IDs. Any other ID, a deleted template included, is refused with 404 template not found.
  • The send uses the published copy of the template. Changes in its draft are not sent until you publish them. A template with no published content is refused with 400.
  • The message has the template’s HTML body with its preview text, and the template’s text body. It has no AMP part. The request cannot carry text_content, html_content or amp_content, and is refused with 400 when it does.
  • Get Message returns the ID of the template in the message’s template_id.
Sender and subject:
  • Leave out from to send from the template’s default sender. A from in the request is used even when the template has a default sender.
  • When the request has no from and the template has no default sender, the request is refused with 400 from is required because the template has no default sender.
  • The sender, the request’s or the template’s, must be from a domain you own with valid DNS records.
  • When the request has no reply_to and no reply-to header, the template’s reply-to is used.
  • subject replaces the template’s subject. When it is left out, empty or only spaces, the template’s published subject is used. When neither has a subject, the request is refused with 400.
Variables:
  • Each recipient’s substitutions hold its values for the template’s variables. They are the only place for these values: a substitutions object at the top of the request is refused with 400.
  • Each recipient must give a value for each required variable of the template. The variables list of Get Template shows which variables are required. A variable that the design wraps in a fallback is not required. An empty value counts as a value.
  • When a recipient does not give a required variable, the request is refused with 400, and no message is sent. The error names each recipient and the variables it does not give, for example missing required template variables: user@example.com needs first_name, order_id.
  • A value for a name that the template does not use is accepted. Your subject and headers resolve from the same values, and a {{ name }} with no value becomes empty.
  • In the HTML body, each value is HTML-escaped. A design that writes {{ name|safe }} inserts that value as HTML. The subject, the headers and the text body get values as they are.
  • The send supplies email and unsubscribe_url itself and replaces a value a recipient gives for them. email is the recipient’s address.
Unsubscribe link: When the template’s design uses unsubscribe_url, each recipient gets its own unsubscribe link. The message carries List-Unsubscribe with that link and List-Unsubscribe-Post: List-Unsubscribe=One-Click, so the unsubscribe button of a mail client works. The button suppresses the recipient for the sending domain. The link opens a confirmation page, and the recipient is suppressed after they confirm. A List-Unsubscribe or List-Unsubscribe-Post in your headers is dropped. When the design does not use unsubscribe_url, the send makes no link and sends your headers as you give them. Other fields: attachments, headers, tags, tracking, retention, schedule, sandbox and sandbox_result follow the rules of Create Message. The response is the same per-recipient list. When sending from the domain is paused, the request is refused with 403. A sandbox message is accepted from a paused domain. This operation accepts an Idempotency-Key header. See Idempotency.

Authorizations

Authorization
string
header
required

API key for authentication. Non-empty Security Requirement values are AhaSend API-key roles. Roles listed within one requirement object are jointly required; separate requirement objects are alternatives.

Headers

Idempotency-Key
string

Optional idempotency key for safe request retries. Must be a unique string for each logical request. An identical request with a completed stored outcome returns the original status and body. An in-progress execution returns 409, a changed method/path/body returns 422, and a released 5xx execution may run again. Keys for non-secret responses expire after 24 hours. API-key create responses include a one-time secret_key, so successful encrypted replay responses for those operations expire after 5 minutes.

Maximum string length: 255

Path Parameters

account_id
string<uuid>
required

Account ID

Body

application/json
template_id
string<uuid>
required

The ID of one of this account's transactional templates. List Templates returns the IDs.

recipients
object[]
required

Each recipient gets a separate message. This does not set the To header to more than one address.

A recipient's substitutions hold its values for the template's variables. They are the only place for these values.

Required array length: 1 - 100 elements
from
object

The sender. Leave it out to send from the template's default sender. A from given here is used even when the template has a default sender, and it must have an email.

Example:
reply_to
object

If provided, the reply-to header in headers must not be provided. When the request has neither, the template's reply-to is used.

Example:
subject
string

Email subject line. When it is left out, empty or only spaces, the template's published subject is used.

A {{ variable }} in the subject, yours or the template's, resolves for every recipient from that recipient's substitutions and the reserved variables, whatever else the subject contains -- an emoji or an accented character included. A variable with no value becomes empty.

Pad the braces with ordinary spaces: a variable written with non-ASCII whitespace inside them is not reliably recognised.

On a subject that carries a {{ variable }} and an emoji or an accented character, template syntax other than a variable -- {% ... %}, {# ... #} or an unclosed brace -- is rejected. A substitution value is rejected for any of {{, {% or {#, a {{ ... }} included, and so is a subject whose values combine into one of them.

attachments
object[]

File attachments. For an inline image, set the attachment's content_id to a value wrapped in angle brackets (e.g. <image1@example.com>). The template's HTML can then show it with cid: (e.g. <img src="cid:image1@example.com">).

headers
object

Custom email headers. Each name must be visible ASCII with no space and no colon. reply-to header cannot be provided if reply_to is provided, message-id will be ignored and automatically generated.

A {{ variable }} in a value resolves from the recipient's substitutions and the reserved variables. On a template whose design uses unsubscribe_url, a List-Unsubscribe or List-Unsubscribe-Post header given here is dropped.

tags
string[]

Tags for categorizing messages

sandbox
boolean
default:false

If true, the message will be sent to the sandbox environment

sandbox_result
enum<string>

The result of the sandbox send

Available options:
deliver,
bounce,
defer,
fail,
suppress
tracking
object | null

Tracking settings for the message, overrides default account settings

Example:
retention
object | null

Retention settings for the message, overrides default account settings

Example:
schedule
object

Schedule for message delivery

Response

Message created successfully

object
enum<string>
required

Object type identifier

Available options:
list
data
object[]
required

List of messages and their statuses