CoolMail
Developer API

CoolMail API

Create temporary inboxes and get verification codes straight from your code — no inbox UI, no browser. The same infrastructure as the dashboard, over a Bearer token.

Start in 3 steps

  1. 1Create your account and top up via Pix (R$ 5.00 ≈ US$ 1 = 1 inbox)
  2. 2Create your key in the Dashboard, API section
  3. 3Call the API — the /code endpoint hands you the code ready

Quickstart

https://coolmail.click/api/v1
terminal
# 1) creates the inbox and returns the addresscurl -s -X POST https://coolmail.click/api/v1/inboxes \  -H "Authorization: Bearer cmk_live_YOUR_API_KEY" \  -H "Content-Type: application/json" -d '{}' # 2) long-poll: holds up to 25s waiting for the verification codecurl -s "https://coolmail.click/api/v1/inboxes/YOUR_INBOX_ID/code?wait=25" \  -H "Authorization: Bearer cmk_live_YOUR_API_KEY"
response.json
{  "status": "ok",  "codigo": "482913",  "alts": [],  "from": "no-reply@example.com",  "subject": "Your verification code",  "received_at": 1760000000000,  "message_id": "b2c4…",  "address": "raposa-azul-4821@exemplo.com"}

Authentication

Every route requires an Authorization header with your key (cmk_live_… format). The key is shown exactly once at creation — store it safely and revoke it in the dashboard if it leaks.

Authorization: Bearer cmk_live_Ab3xY…

Endpoints

MethodRouteDescription
GET/meBalance, email and key info
POST/inboxesCreates an inbox (R$ 5.00; custom alias R$ 10.00). Optional fields: alias and domain (pool TLD, same price)
GET/domainsPool domains — use in the POST /inboxes domain field
GET/inboxesLists your inboxes with message counts
GET/inboxes/{id}Inbox detail
GET/inboxes/{id}/messagesLast 100 messages (newest first)
GET/messages/{id}Full message (text, HTML, code, links)
GET/inboxes/{id}/code?wait=25Long-poll: waits up to 25s and returns the ready code

The endpoint you actually want: /code

Sign-up automation doesn't want to read email — it wants the code. /code holds the connection for up to 25 seconds, handles MIME parsing, RFC 2047 decoding and the code heuristics for you. No coded message in time? You get a timeout — just call again.

quickstart.py
import requests K = {"Authorization": "Bearer cmk_live_YOUR_API_KEY"}base = "https://coolmail.click/api/v1" inbox = requests.post(f"{base}/inboxes", headers=K, json={}).json()print(inbox["address"])   # paste it at the site's sign-up r = requests.get(f"{base}/inboxes/{inbox['id']}/code",                 headers=K, params={"wait": 25}, timeout=35).json()print(r["codigo"])        # the verification code
quickstart.js
const K = { Authorization: "Bearer cmk_live_YOUR_API_KEY" };const base = "https://coolmail.click/api/v1"; const inbox = await fetch(base + "/inboxes", {  method: "POST", headers: { ...K, "Content-Type": "application/json" },  body: "{}",}).then((r) => r.json()); const code = await fetch(base + "/inboxes/" + inbox.id + "/code?wait=25", {  headers: K,}).then((r) => r.json()); console.log(code.codigo);

Webhooks: the code lands on your server

Don't want to poll? Register an https endpoint in the Dashboard (Webhooks section) and CoolMail sends a signed POST the instant the email arrives — with the code already extracted by the same heuristics as /code. No per-delivery cost.

payload.json
{  "type": "message.received",  "created_at": 1760000000000,  "data": {    "message_id": "9f1c8a…",    "address": "raposa-azul-4821@exemplo.com",    "from": "no-reply@example.com",    "subject": "Your verification code",    "codigo": "482913",    "alts": ["482913"],    "links": ["https://exemplo.com/verify?token=…"],    "received_at": 1760000000000,    "text": "Your code is 482913. It expires in…"  }}

Verifying the signature

Every delivery carries the header X-CoolMail-Signature: t=<unix>,v1=hmac_sha256(secret, "<t>.<body>") — same scheme as Stripe. Validate it with the whsec_… secret you received at webhook creation (and check |now − t| < 5 min to block replay):

verify.py
import hmac, hashlib # v1 is over the RAW body — read the body before parsing itdef verifica(secret, header, raw_body):    partes = dict(p.split("=", 1) for p in header.split(",")]    esperado = hmac.new(        secret.encode(), f"{partes['t']}.".encode() + raw_body,        hashlib.sha256,    ).hexdigest()    return hmac.compare_digest(esperado, partes["v1"])
verify.js
import crypto from "node:crypto"; // v1 is over the RAW body — read the body before parsing itfunction verifica(secret, header, rawBody) {  const p = Object.fromEntries(    header.split(",").map((x) => x.split("="))  );  const esperado = crypto    .createHmac("sha256", secret)    .update("${p.t}." + rawBody)    .digest("hex");  return crypto.timingSafeEqual(    Buffer.from(esperado), Buffer.from(p.v1)  );}
  • At-least-once delivery: the same message_id may arrive more than once — dedupe on your side
  • 10s timeout per attempt + 1 immediate retry; 20 consecutive failures pause the webhook (re-enable it in the dashboard)
  • The payload has no HTML — the full body is GET /v1/messages/{id} with your key
  • Up to 3 active endpoints per account, managed in the Dashboard (Webhooks section)

MCP Server

Connect AI agents (Claude, Cursor, Cline…) to CoolMail via Model Context Protocol: the agent creates the inbox, waits for the email and reads the verification code — no dashboard, no copy-paste.

create_inboxcreates an inbox (debits R$5 from the balance — the MCP client asks for your confirmation; max 100/day per key). Optional params: alias and domain (pool TLD, same price — the tool description lists the available domains)
list_inboxeslists the account's inboxes
wait_for_emaillong-polls for up to 25s waiting for a verification code to arrive in the inbox
get_messagereads the full content of a message (text body, code and links)
extract_otpextracts just the verification code from a message
extract_linksextracts links from a message (best-guess verification link first)

Errors

Every error response is JSON {erro, codigo}. Stable codes:

401chave_ausente / chave_invalida / chave_revogadaAuthorization problem
402saldo_insuficientecomes with precisa_cents — top up in the dashboard
400dominio_invalidodomain outside the pool — get the list at GET /domains
404—inbox/message doesn't exist or isn't yours (never 403)
409alias_em_usocustom alias already taken
429rate_limitedper-key limit exceeded

Limits

  • 10 inboxes/min, 30 /code calls/min and 120 reads/min, per key
  • 100 inboxes/day per key (daily cap, shared by the REST API and MCP)
  • wait capped at 25s per /code call (loop on your side)
  • GET /messages/{id} returns text, html, codigo, alts and links (every URL in the message; the first is the best-guess verification link — a single-URL message returns it directly)
  • Lists return up to 100 messages; /code searches the 10 newest
  • Emails above 512KB are truncated (parsing tolerates it)
  • Inboxes are permanent: pay once, receive forever

Pricing

Same price as the dashboard, debited from the same Pix wallet: R$ 5.00 (~US$ 1) per inbox with a random alias, R$ 10.00 with an alias you pick. Picking the domain (TLD) costs the same. No subscription, no charge for received messages.