Documentation Index
Fetch the complete documentation index at: https://ahasend.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Template System
The AhaSend CLI uses Jinja2 templating for creating personalized emails.
Template Basics
Use double curly braces for variable substitution:
<!-- template.html -->
<h1>Hello {{first_name}}!</h1>
<p>Welcome to {{company_name}}.</p>
<p>Your account type is: {{account_type}}</p>
Substitution Types
Global Substitutions
Applied to all recipients - use for company-wide data:
{
"company_name": "ACME Corporation",
"support_email": "support@acme.com",
"year": "2024"
}
ahasend messages send \
--from sender@example.com \
--to recipient@example.com \
--html-template template.html \
--global-substitutions company-data.json
Recipient Substitutions
Per-recipient data from CSV/JSON files:
ahasend messages send \
--from sender@example.com \
--recipients users.csv \
--html-template template.html \
--global-substitutions company-data.json
Basic Examples
Simple Template
<!-- welcome.html -->
<!DOCTYPE html>
<html>
<body>
<h1>Welcome {{first_name}}!</h1>
<p>Thank you for joining {{company_name}}.</p>
<p>Your account type: {{account_type}}</p>
<p>Questions? Contact {{support_email}}</p>
</body>
</html>
Conditional Content
<!-- conditional.html -->
<h1>Hello {{first_name}}!</h1>
{% if account_type == "premium" %}
<p>Thank you for being a Premium member!</p>
{% else %}
<p>Consider upgrading to Premium!</p>
{% endif %}
Lists and Loops
<!-- order-confirmation.html -->
<h1>Order Confirmation</h1>
<p>Thank you, {{customer_name}}!</p>
<table>
{% for item in items %}
<tr>
<td>{{item.name}}</td>
<td>{{item.quantity}}</td>
<td>${{item.price}}</td>
</tr>
{% endfor %}
</table>
Testing Templates
Test templates using sandbox mode:
ahasend messages send \
--from test@example.com \
--to test@example.com \
--html-template template.html \
--global-substitutions test-data.json \
--sandbox
Then check the AhaSend dashboard to see the rendered message.
Best Practices
- Use meaningful variable names:
{{customer_first_name}} not {{fn}}
- Provide default values:
{{name|default("Friend")}}
- Test with real data: Use sandbox mode before sending
- Keep templates simple: Complex logic belongs in your application
- Global vs recipient data: Company info in global, personal info per recipient
Next Steps