K
Koltrix docs

Sending email

There are three ways to send mail through Koltrix:

  1. REST APIPOST /api/v2/emails, JSON, idempotent.
  2. SMTP relay — port 2525, AUTH PLAIN with your API key as password.
  3. Campaigns — broadcast to a list from the dashboard or via the API.

All three go through the same pipeline, so bounces, suppression, opens, clicks, and webhooks behave identically.

REST

curl https://api.koltrix.com/api/v2/emails \
  -H "Authorization: Bearer kx_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "from": "[email protected]",
    "to": ["[email protected]"],
    "cc": ["[email protected]"],
    "subject": "Hello",
    "body_html": "<p>Hi</p>",
    "body_text": "Hi"
  }'
HeaderNotes
AuthorizationRequired. Bearer kx_...
Idempotency-KeyRecommended. Any unique string per logical send. Cached 24h per key.
Content-Typeapplication/json

Node (fetch)

import { randomUUID } from "node:crypto";
 
await fetch("https://api.koltrix.com/api/v2/emails", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.KOLTRIX_KEY!}`,
    "Content-Type": "application/json",
    "Idempotency-Key": randomUUID(),
  },
  body: JSON.stringify({
    from: "[email protected]",
    to: ["[email protected]"],
    subject: "Hello",
    body_html: "<p>Hi</p>",
  }),
});

Python

import os, uuid, requests
 
requests.post(
    "https://api.koltrix.com/api/v2/emails",
    headers={
        "Authorization": f"Bearer {os.environ['KOLTRIX_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "from": "[email protected]",
        "to": ["[email protected]"],
        "subject": "Hello",
        "body_html": "<p>Hi</p>",
    },
)

Go

req, _ := http.NewRequest("POST", "https://api.koltrix.com/api/v2/emails",
    strings.NewReader(`{"from":"[email protected]","to":["[email protected]"],"subject":"Hi","body_html":"<p>Hi</p>"}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("KOLTRIX_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.New().String())
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

Status flow

Every send writes a row in outbound_messages that walks through states:

queued ─► sent ─► delivered ─► opened ─► clicked
   └────► bounced (auto-suppressed on 5xx)
   └────► failed

You can subscribe to any of these via webhooks and view a live feed in Settings → Email logs.

Idempotency

When the network blinks and your client retries, you don't want two copies of the welcome email. Include Idempotency-Key: <unique-string> and we cache the first response for 24 hours per (tenant, key). Subsequent calls with the same key return the original response with header Idempotent-Replayed: true.