package main
import (
"context"
"fmt"
"log"
"os"
"github.com/AhaSend/ahasend-go/api"
"github.com/google/uuid"
)
func main() {
client := api.NewAPIClient(api.WithAPIKey(os.Getenv("AHASEND_API_KEY")))
accountID := uuid.MustParse(os.Getenv("AHASEND_ACCOUNT_ID"))
ctx := context.Background()
templateID := uuid.MustParse("11111111-1111-4111-8111-111111111111")
// The whole draft is published, including changes made in the dashboard.
// The SDK sends a fresh Idempotency-Key with this POST and reuses it on
// its own retries.
response, _, err := client.TemplatesAPI.PublishTemplate(ctx, accountID, templateID)
if err != nil {
log.Fatalf("Error publishing template: %v", err)
}
fmt.Printf("Published template %s\n", response.Name)
}
import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
// The SDK sends a fresh Idempotency-Key automatically and reuses it on its own retries.
const templateId = "00000000-0000-4000-8000-000000000009";
const template = await client.templates.publish(templateId);
console.log("Template published.", { id: template.id, hasDraft: template.has_draft });
curl --request POST \
--url https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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}/templates/{template_id}/publish")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "template",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"name": "<string>",
"subject": "<string>",
"preheader": "<string>",
"variables": [
{
"name": "<string>",
"required": true
}
],
"from": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"reply_to": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"editor": "advanced",
"has_draft": true,
"content": {
"text_is_custom": true,
"mjml": "<string>",
"html": "<string>",
"text": "<string>"
}
}{
"message": "Error message"
}{
"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"
}{
"message": "Error message"
}{
"message": "template is being changed by another request, try again"
}Publish a Template Draft via the API
Publish the draft of an AhaSend transactional template so that sends use it. Each published draft is kept as a new version of the template.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/AhaSend/ahasend-go/api"
"github.com/google/uuid"
)
func main() {
client := api.NewAPIClient(api.WithAPIKey(os.Getenv("AHASEND_API_KEY")))
accountID := uuid.MustParse(os.Getenv("AHASEND_ACCOUNT_ID"))
ctx := context.Background()
templateID := uuid.MustParse("11111111-1111-4111-8111-111111111111")
// The whole draft is published, including changes made in the dashboard.
// The SDK sends a fresh Idempotency-Key with this POST and reuses it on
// its own retries.
response, _, err := client.TemplatesAPI.PublishTemplate(ctx, accountID, templateID)
if err != nil {
log.Fatalf("Error publishing template: %v", err)
}
fmt.Printf("Published template %s\n", response.Name)
}
import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
// The SDK sends a fresh Idempotency-Key automatically and reuses it on its own retries.
const templateId = "00000000-0000-4000-8000-000000000009";
const template = await client.templates.publish(templateId);
console.log("Template published.", { id: template.id, hasDraft: template.has_draft });
curl --request POST \
--url https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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}/templates/{template_id}/publish")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ahasend.com/v2/accounts/{account_id}/templates/{template_id}/publish")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "template",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"name": "<string>",
"subject": "<string>",
"preheader": "<string>",
"variables": [
{
"name": "<string>",
"required": true
}
],
"from": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"reply_to": {
"email": "noreply@example.com",
"name": "Example Corp"
},
"editor": "advanced",
"has_draft": true,
"content": {
"text_is_custom": true,
"mjml": "<string>",
"html": "<string>",
"text": "<string>"
}
}{
"message": "Error message"
}{
"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"
}{
"message": "Error message"
}{
"message": "template is being changed by another request, try again"
}templates:write.
The API and the dashboard edit the same draft. A publish publishes the whole draft, including changes made in the dashboard. To see what a publish will publish, use Get Template Draft first.
A template with no draft and with published content stays as it is, so you can repeat the request safely. A template with no draft and no published content is refused with 400. So is a draft with no content, and a draft whose design or text holds a {{, {% or {# that cannot be rendered. The operation takes no request body.
If the template changes in the dashboard or through another request while this request runs, the API tries again. If that continues, the API answers 503 with a Retry-After header. Retry the request after that delay.
This operation accepts an Idempotency-Key header. A 503 stores no response, so a retry with the same key runs the request again. See Idempotency.
Related Guides
- API authentication, Permission scopes, Idempotency.
- Create Template Message, List Template Versions, API errors, API rate limits.
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.
255Response
Template published
Object type identifier
template Pass as template_id to Create Template Message to send this template
When the template was created
When the template's name or published content last changed
Template name, as it appears in the dashboard
The published subject, set on the template page. Empty until one is published, and overridden by a send that names its own subject.
The published preview text, injected into the delivered HTML when it is set
Every variable the design uses. A send of this template takes the
values only from each recipient's substitutions. Every recipient
must give a value for each required variable; if one does not, the
request is rejected and no message is sent.
Show child attributes
Show child attributes
The default sender, used by a send that names no from. Null when the template has none, and then every send must name one.
Show child attributes
Show child attributes
{
"email": "noreply@example.com",
"name": "Example Corp"
}
The default reply-to address, used by a send that sets no reply-to, also one that names its own from. Null when the template has none. It has the shape of a send request's reply_to; its name is always empty.
Show child attributes
Show child attributes
{
"email": "noreply@example.com",
"name": "Example Corp"
}
The editor the template is designed with. It never changes after the template is created.
advanced: designed in MJML, with the dashboard's advanced editor.simple: designed with the dashboard's simple editor. Its HTML is made from the design and can be read but not changed through the API.html: an HTML template, uploaded or written by hand.
advanced, simple, html Whether the template has a draft, changes saved in the dashboard or through the API that are not published yet. Get Template Draft returns it.
The published content. Null when the published copy has no body, as for a template that was never published. List Templates leaves this field out; every other operation that returns a Template sets it.
Show child attributes
Show child attributes

