Developers

Send your first email with one HTTP call.

Refiremail is a plain REST API at api.refiremail.com. Send JSON with your key in the Authorization header, from any language. There is no SDK to install.

send.shShell
curl -X POST https://api.refiremail.com/emails \
  -H "Authorization: Bearer $REFIREMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042" \
  -d '{
    "from": "Nimbu <[email protected]>",
    "to": ["[email protected]"],
    "subject": "Order #1042 is confirmed",
    "html": "<p>Thanks, Asha. Your order ships tomorrow.</p>"
  }'

01, Quickstart

From a new account to a delivered email.

Three steps. The first two happen once; the third is the code you keep.

  1. Create an API key

    Once your early access is on, create a key in the dashboard under API keys. Give a service that only sends a sending-only key. The key is shown once and stored only as a hash.

    Request early access
  2. Verify your domain

    Add the DKIM and SPF records we show you. We start checking a minute after you add the domain; how soon they are found depends on your DNS host.

    What the records do
  3. Send

    Pick your language. Each tab has the .env and the code, and none of them needs an SDK.

.env
# .env
REFIREMAIL_API_KEY=<your Refiremail key>
send.tsTypeScript
const res = await fetch('https://api.refiremail.com/emails', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.REFIREMAIL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: 'Nimbu <[email protected]>',
    to: ['[email protected]'],
    subject: 'Order #1042 is confirmed',
    html: '<p>Thanks, Asha. Your order ships tomorrow.</p>',
  }),
});

const { id } = await res.json(); // 200 OK → { "id": "…" }

Node 18 or later: fetch is built in.

Shell
pip install requests
.env
# .env
REFIREMAIL_API_KEY=<your Refiremail key>
send.pyPython
import os
import requests

res = requests.post(
    "https://api.refiremail.com/emails",
    headers={"Authorization": f"Bearer {os.environ['REFIREMAIL_API_KEY']}"},
    json={
        "from": "Nimbu <[email protected]>",
        "to": ["[email protected]"],
        "subject": "Order #1042 is confirmed",
        "html": "<p>Thanks, Asha. Your order ships tomorrow.</p>",
    },
    timeout=10,
)
res.raise_for_status()
email_id = res.json()["id"]
.env
# .env
REFIREMAIL_API_KEY=<your Refiremail key>
send.phpPHP
<?php
$ch = curl_init('https://api.refiremail.com/emails');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('REFIREMAIL_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'from' => 'Nimbu <[email protected]>',
        'to' => ['[email protected]'],
        'subject' => 'Order #1042 is confirmed',
        'html' => '<p>Thanks, Asha. Your order ships tomorrow.</p>',
    ]),
]);

$email = json_decode(curl_exec($ch), true); // ['id' => '…']

Uses PHP’s curl extension, which most hosts enable.

send.shShell
curl -X POST https://api.refiremail.com/emails \
  -H "Authorization: Bearer $REFIREMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042" \
  -d '{
    "from": "Nimbu <[email protected]>",
    "to": ["[email protected]"],
    "subject": "Order #1042 is confirmed",
    "html": "<p>Thanks, Asha. Your order ships tomorrow.</p>"
  }'

The key goes in the Authorization header.

02, Switch

Switching is a config change, not a rewrite.

Keep your request shapes: point your existing integration at api.refiremail.com, swap in a Refiremail key, and redeploy. Your send code, your templates and your webhook handler stay as they are.

Redo once, on our side. Three things belong to your account rather than your code:

  • Verify your sending domain with us. The DKIM records are new, because the signing key is ours.
  • Create your webhook endpoints again. Each gets a new signing secret; a Standard Webhooks check keeps working.
  • Bring your contacts across with a CSV import or the contacts API.
.envDiff
removed: EMAIL_API_URL=<your current provider’s API>
added: EMAIL_API_URL=https://api.refiremail.com
removed: EMAIL_API_KEY=<your current key>
added: EMAIL_API_KEY=<your Refiremail key>from the dashboard

Whatever your code calls them, the base URL and the key are the two values that change. Requests keep their shape: POST /emails with from, to, subject and html, and the same idempotency, pagination and error conventions.

03, Endpoints

Every endpoint.

Every route of the API, with its methods and its status.

EndpointMethodsStatusNotes
/emailsPOSTLiveSend one email
/emails/batchPOSTLiveUp to 100 emails per call
/emails/{id}GETLiveOne sent email and its latest event
/emailsGETLiveSent emails, newest first
/emails/{id}PATCHLiveReschedule a scheduled email
/emails/{id}/cancelPOSTLiveCancel a scheduled email
/emails/receiving/{id}GETLiveOne received (inbound) email
/domainsGETPOSTPATCHDELETELivePlus POST /domains/{id}/verify
/api-keysGETPOSTPATCHDELETELiveFull-access or sending-only keys
/contactsGETPOSTPATCHDELETELiveLook up by id or by email
/segmentsGETPOSTPATCHDELETELivePlus the contacts in a segment
/topicsGETPOSTPATCHDELETELiveSubscription preferences
/broadcastsGETPOSTPATCHDELETELivePlus send and cancel
/templatesGETPOSTPATCHDELETELivePlus publish; send by id or alias
/automationsGETPOSTPATCHDELETEComingPlus runs and stop. Answers 404 “not available yet” until it opens
/webhooksGETPOSTPATCHDELETELivePlus secret rotation and event replay
/logsGETLiveAPI requests, newest first

Live: built, and covered by passing tests. Coming: not open yet; the API answers it with a 404 that says so.

04, Rules

The rules of the road.

Five things every client of the API should know. Each links to the details.

  • Authentication

    Send Authorization: Bearer <key> on every request. No key is a 401 missing_api_key; a wrong, revoked or expired one is a 403 invalid_api_key.

    Error names
  • Errors

    Every error is JSON with statusCode, name and message. Switch on name, which stays stable when the wording changes.

    The error table
  • Rate limits

    Counted per team, per second. Every response carries ratelimit-limit, ratelimit-remaining and ratelimit-reset; a 429 adds retry-after.

    Limits
  • Idempotency

    Send Idempotency-Key on POST /emails and /emails/batch. Keys are 1–256 characters and kept 24 hours; the same key with a different body is a 409.

    How retries stay safe
  • Pagination

    Lists take limit (1–100, default 20) with after or before, never both, and return { object: "list", has_more, data }, newest first.

    Limits

05, Beyond REST

The same key does more.

SMTP, inbound mail and webhooks use the same API keys, domains and event model as the REST API.

Your first email is one HTTP call away.

Request early access. Once your account is on, create a key, verify your domain and send.