ESEN
We only use essential cookies to make the site work (session, language and theme). We do not use tracking or advertising cookies. Cookie Policy Got it

API v1

Base URL: https://zend24.com/api/v1 · Auth: Authorization: Bearer sk_live_...

POST /emails

Sends an email. Fields: from, to (string or array, max 50), subject, and html, text or template + variables. Optional: cc, bcc, reply_to.

{
  "from": "App <noreply@yourdomain.com>",
  "to": ["one@example.com"],
  "subject": "Welcome, {{name}}",
  "template": "welcome",
  "variables": { "name": "Ana" }
}
→ 200 { "id": "01J2ZK7QW9..." }

Examples in your language:

curl -X POST https://zend24.com/api/v1/emails \
  -H "Authorization: Bearer sk_live_TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "App <noreply@yourdomain.com>",
    "to": "one@example.com",
    "subject": "Welcome, Ana",
    "html": "<h1>Thanks for your purchase</h1>"
  }'
const res = await fetch("https://zend24.com/api/v1/emails", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_live_TU_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    from: "App <noreply@yourdomain.com>",
    to: "one@example.com",
    subject: "Welcome, Ana",
    html: "<h1>Thanks for your purchase</h1>",
  }),
});
console.log(await res.json());
import requests

requests.post(
    "https://zend24.com/api/v1/emails",
    headers={"Authorization": "Bearer sk_live_TU_API_KEY"},
    json={
        "from": "App <noreply@yourdomain.com>",
        "to": "one@example.com",
        "subject": "Welcome, Ana",
        "html": "<h1>Thanks for your purchase</h1>",
    },
)
<?php
$ch = curl_init('https://zend24.com/api/v1/emails');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_live_TU_API_KEY', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'from' => 'App <noreply@yourdomain.com>', 'to' => 'one@example.com',
    'subject' => 'Welcome, Ana', 'html' => '<h1>Thanks for your purchase</h1>',
  ]),
]);
echo curl_exec($ch);
require 'net/http'
require 'json'

uri = URI('https://zend24.com/api/v1/emails')
req = Net::HTTP::Post.new(uri, {
  'Authorization' => 'Bearer sk_live_TU_API_KEY',
  'Content-Type'  => 'application/json'
})
req.body = {
  from: 'App <noreply@yourdomain.com>', to: 'one@example.com',
  subject: 'Welcome, Ana', html: '<h1>Thanks for your purchase</h1>'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
package main

import ("bytes"; "io"; "net/http")

func main() {
	body := []byte(`{"from":"App <noreply@yourdomain.com>","to":"one@example.com","subject":"Welcome, Ana","html":"<h1>Thanks for your purchase</h1>"}`)
	req, _ := http.NewRequest("POST", "https://zend24.com/api/v1/emails", bytes.NewBuffer(body))
	req.Header.Set("Authorization", "Bearer sk_live_TU_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	println(string(out))
}

Attachments

Add the attachments field (array). Each item: filename, content (the file contents in base64) and optional content_type (MIME). Up to 20 files and 1 MB total.

{
  "from": "App <noreply@yourdomain.com>",
  "to": "one@example.com",
  "subject": "Your July invoice",
  "html": "<h1>Thanks for your purchase</h1>",
  "attachments": [
    {
      "filename": "factura.pdf",
      "content_type": "application/pdf",
      "content": "JVBERi0xLjQKJ..."   # base64
    }
  ]
}

POST /emails/batch

Up to 100 sends in one call: { "emails": [ {...}, {...} ] }. Returns a result per index.

GET /emails/{id} · GET /emails

Individual status (status, opens, clicks) or paginated list with ?limit=&before= (cursor).

GET /domains · GET /suppressions · DELETE /suppressions/{email}

Domain status and suppression list management (DELETE requires a key with full scope).

Webhooks

Events: email.sent, email.delivered, email.bounced, email.complained, email.opened, email.clicked. Every POST includes X-Zend24-Timestamp and X-Zend24-Signature: v1=HMAC_SHA256(ts.body, secret). Verify the signature and reject timestamps older than 5 minutes.

Errors and limits

Errors: { "error": { "type", "message" } } with standard HTTP codes (401 auth, 403 domain, 422 validation, 429 rate limit/quota). The per-minute rate limit depends on your plan.