Newsletters
A list is a group of people you send the same email to. You add subscribers to it and send a broadcast: one message, delivered to every active subscriber as their own copy, with an unsubscribe link. For timed series, such as a welcome series, see Sequences.
Broadcasts use the same pipeline as everything else you send, so they share your suppression list: someone who unsubscribed or bounced is never mailed again by any list.
Every endpoint is in the API reference. Reading
needs a key with the read or newsletter scope; anything that changes data
needs newsletter.
Lists
curl https://api.koltrix.com/api/v2/lists \
-H "Authorization: Bearer $KOLTRIX_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Product updates",
"description": "What shipped this month",
"from_name": "Acme",
"from_address": "[email protected]"
}'{
"id": "0b3c6d2e-91f4-4a7b-8c5d-2e3f4a5b6c7d",
"name": "Product updates",
"description": "What shipped this month",
"from_name": "Acme",
"from_address": "[email protected]",
"reply_to": "",
"subscriber_count": 0,
"created_at": "2026-10-02T10:11:12Z",
"updated_at": "2026-10-02T10:11:12Z"
}from_name and from_address are the default sender for broadcasts and
sequences on the list. Use an active address on a verified domain, as for any
send. subscriber_count counts active subscribers.
| Action | Request |
|---|---|
| List all lists | GET /api/v2/lists |
| Get one | GET /api/v2/lists/:id |
| Change fields | PATCH /api/v2/lists/:id with only the fields to change |
| Delete, with its subscribers | DELETE /api/v2/lists/:id (returns 204) |
Subscribers
Add one
curl https://api.koltrix.com/api/v2/lists/$LIST_ID/subscribers \
-H "Authorization: Bearer $KOLTRIX_KEY" \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]", "name": "Ada Lovelace", "tags": ["beta"] }'The response is 201 with the subscriber, including its id and status.
- Adding an email that is already on the list updates the name instead of failing. Someone who unsubscribed stays unsubscribed.
- A new active subscriber is enrolled in the list's sequences.
status | Meaning |
|---|---|
active | Receives broadcasts and sequences. |
pending | Waiting to confirm a double opt-in. |
unsubscribed | Opted out. Also on your suppression list. |
Lists created through the API don't require double opt-in, so subscribers you
add are active straight away. Only add people who asked to hear from you.
Import many
Send a CSV file's contents as a string:
curl https://api.koltrix.com/api/v2/lists/$LIST_ID/subscribers/import \
-H "Authorization: Bearer $KOLTRIX_KEY" \
-H "Content-Type: application/json" \
-d '{ "csv": "email,name,tags\[email protected],Ada Lovelace,beta;vip\[email protected],Linus,beta" }'{ "imported": 2, "skipped": 0, "errors": null }- A header row with
email,name(orfirst_nameorfull_name) andtagscolumns is recognised. Without one, the first column is the email. - Separate tags with semicolons.
- Rows with an invalid email are skipped and counted in
skipped. - Every imported row becomes
active, even on a list that requires double opt-in. Addresses on your suppression list are still never mailed. - Importing doesn't enrol anyone in sequences. Add people one at a time if they should start a sequence.
List, unsubscribe, delete
# Active subscribers, 100 at a time
curl "https://api.koltrix.com/api/v2/lists/$LIST_ID/subscribers?status=active&limit=100&offset=0" \
-H "Authorization: Bearer $KOLTRIX_KEY"
# Unsubscribe: also stops their sequences and suppresses the address
curl -X POST https://api.koltrix.com/api/v2/lists/$LIST_ID/subscribers/$SUB_ID/unsubscribe \
-H "Authorization: Bearer $KOLTRIX_KEY"
# Delete the record from the list
curl -X DELETE https://api.koltrix.com/api/v2/lists/$LIST_ID/subscribers/$SUB_ID \
-H "Authorization: Bearer $KOLTRIX_KEY"The list response is {"data": [...], "total": 1284}. Unsubscribing answers
{"status": "unsubscribed"}; deleting answers 204. Prefer unsubscribing:
deleting the record doesn't add the address to your suppression list.
Broadcasts
curl https://api.koltrix.com/api/v2/lists/$LIST_ID/broadcast \
-H "Authorization: Bearer $KOLTRIX_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "What shipped in October",
"body_html": "<p>Hi {{first_name|there}},</p><p>This month we shipped…</p>",
"preheader": "Faster search and a new inbox"
}'{
"campaign_id": "1d2c3b4a-5f6e-4d7c-8b9a-0f1e2d3c4b5a",
"status": "queued",
"message": "Broadcast enqueued — recipients will be fanned out by the worker."
}Body fields
subjectrequiredbody_htmlrequiredbody_textpreheaderfrom_name, from_addressfrom_address is required if the list has none.Each active subscriber gets their own copy with:
- an unsubscribe link at the end and a
List-Unsubscribeheader, so mail providers can show their own Unsubscribe button, - open tracking, and links rewritten for click tracking,
- the merge variables below filled in.
A broadcast from a new domain is paced by its daily sending cap; one that would
go over today's cap is paused. See Deliverability.
Each copy appears in your message log (GET /api/v2/messages) and fires
webhooks like any other send.
Merge variables
These are filled in per recipient in broadcast bodies:
| Variable | Becomes |
|---|---|
{{name}} | The subscriber's name, or nothing. |
{{first_name}} | The first word of the name, or nothing. |
{{first_name|there}} | The first name, or the fallback after the bar (here, "there"). |
{{email}} | The subscriber's address. |
{{unsubscribe_url}} | Their personal unsubscribe link. |
In HTML bodies, names are HTML-escaped, so a subscriber can't inject markup into your email. A variable Koltrix doesn't recognise is left exactly as written.
Merge variables work in broadcasts and sequences, but not in
POST /api/v2/emails, which sends your text unchanged.
Signup forms
Embedded signup forms need the Newsletters screen to give you a form's address,
and that screen isn't available in this release. Until it returns, add people
from your own backend with POST /api/v2/lists/:id/subscribers after they sign
up on your site.