ahasend messages send its content, from flags or files, and how to personalize it with substitutions.
To send a transactional template stored in your AhaSend account instead, see Stored Templates and the
ahasend templates commands.YOUR_RESOURCE_ID with the ID of a published template in your test account. Create any named content, recipient, or JSON files first. Shell examples use Bash. Sends use sandbox mode.
Content Flags
Give each part of the message inline or from a file, not both:- Text or HTML content is required. AMP content is an extra part that goes with one of them.
- Several parts together make a multipart email.
--textwith--text-file,--htmlwith--html-file, or--ampwith--amp-filefails with exit code 4.
Substitution Basics
The subject and the content can hold placeholders in double curly braces. The AhaSend API fills them for each recipient with MiniJinja, which uses Jinja2-compatible syntax.welcome.html
A recipient’s own value for a key wins over the global value of the same key. The API HTML-escapes values in the HTML and AMP content, so send them as plain text. The subject, custom headers and the text content get values as they are. Use
{{ name|safe }} only for HTML that your own code builds.
Substitution Types
Global Substitutions
Use global substitutions for values that are the same for every recipient. They work with--to and with --recipients.
company-data.json
Recipient Substitutions
Use a recipients file for values that differ per recipient. The file’s extension,.csv or .json, sets its format.
- CSV Format
- JSON Format
users.csv
email column is required, and name sets the display name. The two headers can be in any case. Every other column is a substitution, and every value is trimmed. An empty cell sets no value, so the global value of the same name, if any, applies to that recipient.Template Syntax Examples
Variables and Defaults
default gives a value to use when a variable is missing:
greeting.html
Conditional Content
conditional.html
Lists and Loops
A loop needs a list, so its values come from a JSON recipients file or the global substitutions file. CSV cells hold text only.order-confirmation.html
orders.json
Stored Templates
--template-id sends a transactional template that is stored in your AhaSend account, instead of content from flags or files. Create, publish and inspect stored templates with the ahasend templates commands. ahasend templates get lists the variables that a send must supply.
- The template supplies the content, so the content flags on this page cannot be used with
--template-id. --fromand--subjectare optional. Without them, the template’s sender and subject apply.- Substitutions work as on this page: the values of
--global-substitutionsare copied into each recipient’s substitutions, and a recipient’s own value wins.
Testing Content
Send to a test address in sandbox mode, which delivers nothing:ahasend messages get with its Message-ID to see its content. See messages get.
Best Practices
- Use meaningful variable names:
{{ customer_first_name }}, not{{ fn }}. - Provide default values:
{{ name|default("Friend") }}. - Test in sandbox mode: Send to a test address before a real send.
- Keep templates simple: Complex logic belongs in your application.
- Split global and recipient data: Company details go in the global file, personal details in the recipients file.
Next Steps
- Learn about batch processing
- Manage stored templates
- Explore the MiniJinja documentation
- View CLI examples

