Examples

Send a transactional email

Complete Send API workflow for sending one transactional message.

This example uses the Send API to send one transactional email from an existing Delivery account.

Workflow and API calls

StepAPI callWhat happens
1Panel setupCreate or choose a Delivery account and Send API token.
2DNS setupMake sure the sending domain is assigned and verified for the Delivery account.
3POST /v1/sendQueue one message for delivery.
4Response handlingStore request_id and message_id for logs and troubleshooting.

Before you start

  • Use a Send API token in the Authorization: Bearer <SEND_API_TOKEN> header.
  • Do not use a Management API token for /v1/send.
  • The sender domain must already be configured on the Delivery account.

Full TypeScript example

type SendResponse = {
  error_code: number;
  message: string;
  request_id: string;
  queued_messages: number;
  messages: Array<{
    error_code: number;
    message: string;
    request_id: string;
    message_id: string;
    submitted_at: string;
    to: string;
  }>;
};

const SEND_API_BASE = (process.env.QBOXMAIL_SEND_API_BASE ?? "https://api.qboxmail.com/v1").replace(/\/$/, "");
const SEND_API_TOKEN = requiredEnv("QBOXMAIL_SEND_API_TOKEN");
const FROM_EMAIL = requiredEnv("FROM_EMAIL");
const TO_EMAIL = requiredEnv("TO_EMAIL");

function requiredEnv(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Missing env var: ${name}`);
  return value;
}

async function sendTransactionalEmail(): Promise<SendResponse> {
  const response = await fetch(`${SEND_API_BASE}/send`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${SEND_API_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      messages: [
        {
          from: FROM_EMAIL,
          to: [TO_EMAIL],
          subject: "Your test email",
          text_body: "Hello from Qboxmail Delivery.",
          html_body: "<p>Hello from <strong>Qboxmail Delivery</strong>.</p>",
        },
      ],
    }),
  });

  const payload = (await response.json()) as SendResponse | { message?: string; request_id?: string };

  if (!response.ok) {
    throw new Error(`Send failed: ${response.status} ${JSON.stringify(payload)}`);
  }

  return payload as SendResponse;
}

sendTransactionalEmail()
  .then((result) => {
    console.log({
      requestId: result.request_id,
      queuedMessages: result.queued_messages,
      messageIds: result.messages.map((message) => message.message_id),
    });
  })
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

Run it

Save the code above as send-transactional-email.ts, then run:

export QBOXMAIL_SEND_API_TOKEN="<SEND_API_TOKEN>"
export FROM_EMAIL="sender@example.com"
export TO_EMAIL="recipient@example.net"

npx tsx send-transactional-email.ts

Keep the returned request_id and message_id. They are the fastest way to troubleshoot the message later.

On this page