🟢 LIVE • UPDATES EVERY 5s 🌍
🕐 WAT Time ⚡
--:--:--.---
—
🌍 Your IP ⚡
loading…
Allocated By Internet Provider ♥️
📊 Pool Usage
— / 95
enter key below
🔑 Active Keys
—
enter key below
Quota usage today—%
🚀 DEVELOPER DOCUMENTATION ⚡

🚀 Build with ZMAIL API.

💜 A friendly email API for developers, bots, websites, and automation. Authenticate with a Bearer key, send through one gateway endpoint, and monitor the shared daily pool in real time. ✨

v1API version
DailyShared send pool
WATResets 00:00 UTC+1
BearerAuth scheme

🚀 Getting Started

Send an authenticated request to the developer send endpoint with your Bearer API key.

Requests are authenticated and quota-checked before the email-send handler runs.
POST /api/v1/send
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

🔐 Authentication

Every request uses a Bearer API key in the Authorization header.

Authorization: Bearer YOUR_API_KEY
Never embed a developer API key in browser JavaScript, public HTML, public repos, or client-side bundles. Keep it server-side and proxy the request.

📊 Usage Limits

📊 Every authorized API key draws from a single shared pool of successful sends per WAT (UTC+1) calendar day. When any key uses a slot, the shared counter drops for every other key. The current limit is shown on the live status board.

RequestCounts?
Successful /api/v1/sendYes
Invalid API keyNo
Validation errorNo
Provider / send failureNo
429 responseNo
/api/uploadNo
/api/templatesNo
/api/checkNo
🕛 Resets at 00:00 WAT (UTC+1). Reservation is atomic, so simultaneous requests cannot consume the same final slot.

✉️ Send Email

POST/api/v1/send

{
  "to": "recipient@example.com",
  "subject": "Hello from ZMAIL",
  "body": "<h1>Hello</h1><p>Your message here.</p>"
}
fetch("/api/v1/send", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    to: "recipient@example.com",
    subject: "Hello from ZMAIL",
    body: "<p>Hello!</p>"
  })
});

🖼️ Send With Image

Attach exactly one image per email by passing a base64 data URI in image_base64. The server uploads it to ImgBB and injects the hosted URL into your body automatically.

🖼️ Images do not consume the shared send quota. Only the successful send counts.

Body fields

FieldRequiredNotes
image_base64NoData URI — data:image/jpeg;base64,...
image_altNoAlt text
image_widthNoPixel width, e.g. 600
image_positionNostart · end (default) · replace

Basic example

{
  "to": "recipient@example.com",
  "subject": "Photo attached",
  "body": "<h1>Look at this</h1>",
  "image_base64": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
  "image_width": 600,
  "image_position": "end"
}

Position the image with {{image}}

{
  "body": "<p>Before</p>{{image}}<p>After</p>",
  "image_base64": "data:image/jpeg;base64,...",
  "image_position": "replace"
}
Base64 inflates size by ~33%. Keep payloads under 3 MB to stay below the website's ~4.5 MB limit. For larger images, host externally and place <img src="..."> directly in the body HTML.

Standalone upload endpoint

POST/api/upload

const form = new FormData();
form.append("image", imageFile);   // field name is "image"

const response = await fetch("/api/upload", {
  method: "POST",
  body: form
});

const { url } = await response.json();
console.log(url);   // https://i.ibb.co/...

📝 Templates

GET/api/templates

const response = await fetch("/api/templates");
const data = await response.json();
console.log(data.templates);
📱 On phones, code examples and wide reference tables can be swiped horizontally when needed.

🌍 Every Language & Platform

Copy-paste examples for sending email through /api/v1/send. Pick your stack from the list. Every example uses the same core pattern: Bearer auth, JSON body, POST request.

Loading…

⚠️ Errors

StatusMeaning
400Invalid request data or invalid image request
401Missing or invalid API key
405HTTP method not allowed
413Request / image too large
415Unsupported media type
429Shared daily pool exhausted
500Server or provider failure
503Quota tracking not configured on server
⏳ A 429 means the shared daily pool is exhausted. It does not mean your API key is invalid. The pool resets at 00:00 WAT (UTC+1).

🧪 API Key Tester

🧪 Enter an API key to validate it and populate the live dashboard above. The key is kept in this browser session only.

🛡️ Security

  • 🔒 Keep API keys server-side — never in browser bundles.
  • 🚫 Never commit provider credentials to Git.
  • 🧱 Never expose the Supabase service-role key.
  • 🔁 Rotate a key immediately if you suspect a leak.
  • 🌐 Always use HTTPS for outbound API calls.
  • 🎯 Validate recipients before sending.

🔧 Troubleshooting

401 — Invalid API key

Confirm the key is authorized and the header is Authorization: Bearer <key>.

429 — Daily limit

Check the shared pool with the tester above. Resets at 00:00 WAT (UTC+1).

500 — Server error

Check server logs and the Supabase schema. Provider failures do not consume a slot.

400 — Invalid image request

The detail field names the exact rule violated: mixed sources, more than one image, or a malformed data URI.