package main
import (
"context"
"fmt"
"log"
"github.com/AhaSend/ahasend-go"
"github.com/AhaSend/ahasend-go/api"
"github.com/AhaSend/ahasend-go/models/common"
"github.com/AhaSend/ahasend-go/models/requests"
"github.com/google/uuid"
)
func main() {
// Create API client with authentication
client := api.NewAPIClient(
api.WithAPIKey("aha-sk-your-64-character-key"),
)
accountID := uuid.New()
// Create context for the API call
ctx := context.Background()
response, httpResp, err := client.MessagesAPI.CreateMessage(
ctx,
accountID,
requests.CreateMessageRequest{
From: common.Address{
Email: "info@example.com",
Name: ahasend.String("Example Corp."),
},
Recipients: []common.Recipient{
{
Email: "john@example.com",
Name: ahasend.String("John Smith"),
},
},
Subject: "Hello",
TextContent: ahasend.String("Hello world!"),
Sandbox: ahasend.Bool(true),
},
)
if err != nil {
log.Fatalf("Error sending message: %v", err)
}
// Check response
if httpResp.StatusCode == 202 {
fmt.Printf("✅ Send successful! Status: %d\n", httpResp.StatusCode)
if response != nil {
fmt.Printf("Message ID: %s\n", *response.Data[0].ID)
}
} else {
fmt.Printf("❌ Unexpected status code: %d\n", httpResp.StatusCode)
}
}import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
const result = await client.messages.send(
{
from: { email: "sender@example.com", name: "Example" },
recipients: [{ email: "recipient@example.net" }],
subject: "Hello from AhaSend",
html_content: "<p>Hello!</p>",
sandbox: true,
},
{ idempotencyKey: "sdk-sample-send-message" },
);
console.log("Sandbox message accepted.", { count: result.data.length });
curl --request POST \
--url https://api.ahasend.com/v2/accounts/{account_id}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"from": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"recipients": [
{
"email": "user@example.com",
"name": "John Doe"
}
],
"subject": "Welcome to Example Corp",
"html_content": "<h1>Welcome {{first_name}}!</h1>",
"text_content": "Welcome {{first_name}}!",
"substitutions": {
"first_name": "John"
}
}
'import requests
url = "https://api.ahasend.com/v2/accounts/{account_id}/messages"
payload = {
"from": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"recipients": [
{
"email": "user@example.com",
"name": "John Doe"
}
],
"subject": "Welcome to Example Corp",
"html_content": "<h1>Welcome {{first_name}}!</h1>",
"text_content": "Welcome {{first_name}}!",
"substitutions": { "first_name": "John" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ahasend.com/v2/accounts/{account_id}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'from' => [
'email' => 'noreply@example.com',
'name' => 'Example Corp'
],
'recipients' => [
[
'email' => 'user@example.com',
'name' => 'John Doe'
]
],
'subject' => 'Welcome to Example Corp',
'html_content' => '<h1>Welcome {{first_name}}!</h1>',
'text_content' => 'Welcome {{first_name}}!',
'substitutions' => [
'first_name' => 'John'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}HttpResponse<String> response = Unirest.post("https://api.ahasend.com/v2/accounts/{account_id}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"from\": {\n \"email\": \"noreply@example.com\",\n \"name\": \"Example Corp\"\n },\n \"recipients\": [\n {\n \"email\": \"user@example.com\",\n \"name\": \"John Doe\"\n }\n ],\n \"subject\": \"Welcome to Example Corp\",\n \"html_content\": \"<h1>Welcome {{first_name}}!</h1>\",\n \"text_content\": \"Welcome {{first_name}}!\",\n \"substitutions\": {\n \"first_name\": \"John\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ahasend.com/v2/accounts/{account_id}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"from\": {\n \"email\": \"noreply@example.com\",\n \"name\": \"Example Corp\"\n },\n \"recipients\": [\n {\n \"email\": \"user@example.com\",\n \"name\": \"John Doe\"\n }\n ],\n \"subject\": \"Welcome to Example Corp\",\n \"html_content\": \"<h1>Welcome {{first_name}}!</h1>\",\n \"text_content\": \"Welcome {{first_name}}!\",\n \"substitutions\": {\n \"first_name\": \"John\"\n }\n}"
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"object": "message",
"id": "<uuid@example.com>",
"recipient": {
"email": "user@example.com",
"name": "John Doe",
"substitutions": {
"first_name": "John",
"order_id": "12345"
}
},
"status": "queued",
"error": "<string>",
"schedule": {
"first_attempt": "2023-11-07T05:31:56Z",
"expires": "2023-11-07T05:31:56Z"
}
}
]
}{
"message": "Error message"
}{
"message": "Error message"
}{
"message": "Error message"
}{
"message": "A request with this idempotency key is already in progress"
}{
"message": "idempotency key was already used with a different request payload"
}{
"message": "Error message"
}Create Message
Creates and sends a message to one or more recipients. This API cannot be used if you want to send a conversational/P2P message and set CC or BCC. Use Create Conversation Message instead.
Validation Requirements:
- Either
text_contentorhtml_contentis required from.emailmust be from a domain you own with valid DNS recordsretention.metadatamust be between 1 and 30 daysretention.datamust be between 0 and 30 days- If
reply_tois provided, do not includereply-toin headers message-idheader will be ignored and automatically generated- Schedule times must be in RFC3339 format
schedule.first_attemptmust be in the future and within 7 days of the requestschedule.expiresmust be in the future and within 8 days of the request
Authorization uses the domain in from.email: either
messages:send:all or the matching domain-specific send role is
sufficient.
package main
import (
"context"
"fmt"
"log"
"github.com/AhaSend/ahasend-go"
"github.com/AhaSend/ahasend-go/api"
"github.com/AhaSend/ahasend-go/models/common"
"github.com/AhaSend/ahasend-go/models/requests"
"github.com/google/uuid"
)
func main() {
// Create API client with authentication
client := api.NewAPIClient(
api.WithAPIKey("aha-sk-your-64-character-key"),
)
accountID := uuid.New()
// Create context for the API call
ctx := context.Background()
response, httpResp, err := client.MessagesAPI.CreateMessage(
ctx,
accountID,
requests.CreateMessageRequest{
From: common.Address{
Email: "info@example.com",
Name: ahasend.String("Example Corp."),
},
Recipients: []common.Recipient{
{
Email: "john@example.com",
Name: ahasend.String("John Smith"),
},
},
Subject: "Hello",
TextContent: ahasend.String("Hello world!"),
Sandbox: ahasend.Bool(true),
},
)
if err != nil {
log.Fatalf("Error sending message: %v", err)
}
// Check response
if httpResp.StatusCode == 202 {
fmt.Printf("✅ Send successful! Status: %d\n", httpResp.StatusCode)
if response != nil {
fmt.Printf("Message ID: %s\n", *response.Data[0].ID)
}
} else {
fmt.Printf("❌ Unexpected status code: %d\n", httpResp.StatusCode)
}
}import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
const result = await client.messages.send(
{
from: { email: "sender@example.com", name: "Example" },
recipients: [{ email: "recipient@example.net" }],
subject: "Hello from AhaSend",
html_content: "<p>Hello!</p>",
sandbox: true,
},
{ idempotencyKey: "sdk-sample-send-message" },
);
console.log("Sandbox message accepted.", { count: result.data.length });
curl --request POST \
--url https://api.ahasend.com/v2/accounts/{account_id}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"from": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"recipients": [
{
"email": "user@example.com",
"name": "John Doe"
}
],
"subject": "Welcome to Example Corp",
"html_content": "<h1>Welcome {{first_name}}!</h1>",
"text_content": "Welcome {{first_name}}!",
"substitutions": {
"first_name": "John"
}
}
'import requests
url = "https://api.ahasend.com/v2/accounts/{account_id}/messages"
payload = {
"from": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"recipients": [
{
"email": "user@example.com",
"name": "John Doe"
}
],
"subject": "Welcome to Example Corp",
"html_content": "<h1>Welcome {{first_name}}!</h1>",
"text_content": "Welcome {{first_name}}!",
"substitutions": { "first_name": "John" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ahasend.com/v2/accounts/{account_id}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'from' => [
'email' => 'noreply@example.com',
'name' => 'Example Corp'
],
'recipients' => [
[
'email' => 'user@example.com',
'name' => 'John Doe'
]
],
'subject' => 'Welcome to Example Corp',
'html_content' => '<h1>Welcome {{first_name}}!</h1>',
'text_content' => 'Welcome {{first_name}}!',
'substitutions' => [
'first_name' => 'John'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}HttpResponse<String> response = Unirest.post("https://api.ahasend.com/v2/accounts/{account_id}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"from\": {\n \"email\": \"noreply@example.com\",\n \"name\": \"Example Corp\"\n },\n \"recipients\": [\n {\n \"email\": \"user@example.com\",\n \"name\": \"John Doe\"\n }\n ],\n \"subject\": \"Welcome to Example Corp\",\n \"html_content\": \"<h1>Welcome {{first_name}}!</h1>\",\n \"text_content\": \"Welcome {{first_name}}!\",\n \"substitutions\": {\n \"first_name\": \"John\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ahasend.com/v2/accounts/{account_id}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"from\": {\n \"email\": \"noreply@example.com\",\n \"name\": \"Example Corp\"\n },\n \"recipients\": [\n {\n \"email\": \"user@example.com\",\n \"name\": \"John Doe\"\n }\n ],\n \"subject\": \"Welcome to Example Corp\",\n \"html_content\": \"<h1>Welcome {{first_name}}!</h1>\",\n \"text_content\": \"Welcome {{first_name}}!\",\n \"substitutions\": {\n \"first_name\": \"John\"\n }\n}"
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"object": "message",
"id": "<uuid@example.com>",
"recipient": {
"email": "user@example.com",
"name": "John Doe",
"substitutions": {
"first_name": "John",
"order_id": "12345"
}
},
"status": "queued",
"error": "<string>",
"schedule": {
"first_attempt": "2023-11-07T05:31:56Z",
"expires": "2023-11-07T05:31:56Z"
}
}
]
}{
"message": "Error message"
}{
"message": "Error message"
}{
"message": "Error message"
}{
"message": "A request with this idempotency key is already in progress"
}{
"message": "idempotency key was already used with a different request payload"
}{
"message": "Error message"
}Authorizations
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
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.
255Path Parameters
Account ID
Body
Show child attributes
Show child attributes
{
"email": "noreply@example.com",
"name": "Example Corp"
}
This does not set the To header to multiple addresses, it sends a separate message for each recipient
1 - 100 elementsShow child attributes
Show child attributes
Email subject line
If provided, the reply-to header in headers array must not be provided
Show child attributes
Show child attributes
{
"email": "noreply@example.com",
"name": "Example Corp"
}
Plain text content. Required if html_content is empty
HTML content. Required if text_content is empty
AMP HTML content
File attachments. For inline images, set the attachment's content_id to a value wrapped in angle brackets (e.g. <image1@example.com>) and reference it from html_content with cid: (e.g. <img src="cid:image1@example.com">).
Show child attributes
Show child attributes
Custom email headers. reply-to header cannot be provided if reply_to is provided, message-id will be ignored and automatically generated
Show child attributes
Show child attributes
Global substitutions, recipient substitutions override global
Tags for categorizing messages
If true, the message will be sent to the sandbox environment
The result of the sandbox send
deliver, bounce, defer, fail, suppress Tracking settings for the message, overrides default account settings
Show child attributes
Show child attributes
{ "open": true, "click": true }
Retention settings for the message, overrides default account settings
Show child attributes
Show child attributes
{ "metadata": 1, "data": 0 }
Schedule for message delivery
Show child attributes
Show child attributes

