Quathos Mailer

Templates

Content lives on the server, versioned, and the send references it by id. Templates are sandboxed — they never execute code.

Create a template

A template holds the subject and the body; the send passes template_id and variables, and the body comes from the active version. Placeholders are {{variable}}. The slug is yours and has to be unique per tenant — it is how you find the template again without storing a UUID.

cURL
curl -X POST https://api.qsendyx.com/api/v1/templates \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name":     "Welcome",
    "slug":     "welcome",
    "channel":  "email",
    "subject":  "Welcome, {{first_name}}",
    "html":     "<h1>Hi {{first_name}}</h1><p>You are in.</p>",
    "test_data": { "first_name": "Ada" }
  }'

test_data is the sample used by the preview and by the test send. Keep it filled: it is what lets someone open the template months later and see it rendered instead of a page full of raw placeholders.

Templates never execute code. The engine renders values and escapes them; there is no expression evaluation, no attribute walking, no filesystem. A template you accept from a customer cannot read your server.

GET /templates/gallery lists ready-made designs — newsletter, otp-code, receipt, transactional-basic and welcome. Pass from_gallery with the slug and the design is COPIED into your template.

cURL
curl -X POST https://api.qsendyx.com/api/v1/templates \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name":         "Welcome",
    "slug":         "welcome",
    "channel":      "email",
    "from_gallery": "welcome"
  }'
Copied, not referenced. Once it is yours, changing a gallery design on our side never changes an email of yours — and you can edit it freely without drifting from anything.

Versions, preview and going live

Editing a live template in place would change every send already in flight. Instead, each edit is a version: create it as a draft, preview it, then activate it. The send always uses the active version, so nothing changes until you say so.

http
# 1. novo rascunho (publish: false = não vai para o ar)
curl -X POST https://api.qsendyx.com/api/v1/templates/$ID/versions \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "html": "<h1>New copy</h1>", "publish": false }'

# 2. prévia do rascunho, pelo mesmo sandbox do envio
curl -X POST https://api.qsendyx.com/api/v1/templates/$ID/preview \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "version_id": "$VERSION", "variables": { "first_name": "Ada" } }'

# 3. no ar: publica e ativa
curl -X POST https://api.qsendyx.com/api/v1/templates/$ID/versions/$VERSION/activate \
  -H "Authorization: Bearer $QUATHOS_TOKEN"

The preview renders through the SAME sandbox as the send, with the version test_data underneath and the variables you pass on top. What comes back is the document the send would produce — a preview that renders differently from the send is worse than no preview at all.

Test send

POST /templates/{id}/test_send delivers a real message through the normal pipeline. Accepts version_id, so you can test a draft before publishing it.

cURL
curl -X POST https://api.qsendyx.com/api/v1/templates/$ID/test_send \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "to":        ["you@yourcompany.com"],
    "from":      { "email": "you@yourcompany.com" },
    "variables": { "first_name": "Ada" }
  }'
It goes through the whole pipeline on purpose: verified sender, suppression list, quota and wallet all apply, and it counts. A "free" test send would be a sending endpoint without billing — which is to say, an abuse vector.