Dbrij Send Documentation

Everything you need to implement email with Dbrij Send: domains, sending, templates, audiences, broadcasts, automations, suppressions, receiving, webhooks and limits.

Introduction

Dbrij Send is the email platform for developers: transactional sending, templates, audiences, broadcasts, automations, suppressions, receiving and webhooks, all from your own domain, all through one API. Every message keeps a timeline of what happened to it, and these docs alone are enough to implement email end to end.

Base URLhttps://api.dbrij.com/api

Every endpoint is relative to that base. All requests and responses are JSON. Authenticate with an API key (see Authentication).

Every success response is wrapped in an envelope: { "success": true, "data": … }. Read your payload from data, never from the top level; the Response examples throughout show the envelope. Errors are wrapped the same way with success: false (see Plans, errors and limits).

Quickstart

Three steps from nothing to a delivered email.

1 · Verify your domain. In the Send dashboard, open Domains and add a domain you own. We issue the DKIM, SPF and MX records; publish them at your DNS host and verification completes on its own within minutes.

2 · Create an API key. On the API keys page, create a key with the emails:send scope. You choose the address it sends as when you create it, so the key IS the sender: from can be omitted on every call. Use a test key while building (nothing is relayed, nothing billed) and a live key in production.

3 · Send.

Your first email
curl -X POST https://api.dbrij.com/api/emails \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "to": "jane@example.com",
        "subject": "Hello from Dbrij Send",
        "text": "It works." }'

Then watch it move: GET /emails/:id/events shows the timeline (queued, sent, delivered, opened), and a webhook endpoint (see Webhooks) tells your app the same story as it happens.

Authentication

Authenticate every request with an API key from the Send dashboard, sent as a Bearer token.

Authorization header
Authorization: Bearer dbrij_live_xxxxxxxxxxxxxxxxxxxxxxxx

A key created with the emails:send scope is bound to one sender address, chosen at creation from the addresses your account can send as. Every send through that key goes out as that address, and from can be omitted entirely, so a leaked key is one identity, never a whole domain.

No email ever goes out as a bare address. The display name is, in order: the one in your from string ("Acme Billing <billing@acme.com>"), the sender name on your key, or the domain said like a name: hello@ricuit.com arrives as Ricuit <hello@ricuit.com>, never as "hello".

Test keys. A key created in the test environment (dbrij_test_…) runs the whole pipeline (validation, suppression, tracking, events, webhooks) but delivery is simulated: nothing is relayed, nothing counts against your plan. The email comes back with "sandbox": true and status delivered.

SCOPES

emails:sendscopeSend, schedule and cancel emails.
emails:readscopeRead emails, timelines, domains, stats and every list.
templates:writescopeCreate and edit templates.
audiences:writescopeManage audiences and contacts.
broadcasts:sendscopeCreate, send and cancel broadcasts.
automations:writescopeCreate and manage automations.
suppressions:writescopeAdd and remove suppressions.
webhooks:managescopeManage webhook endpoints and replay deliveries.
inbound:readscopeRead received email.

Domains

Send delivers from your own domain: each one gets its own DKIM key on our delivery network, and DMARC aligns because the mail really is yours. Add and verify domains on the Send dashboard's Domains page; a domain can also be granted to you by the company that owns it (from company email settings), which authorizes your keys without giving you the domain.

Each domain carries three switches on the dashboard: open tracking (a pixel per email), click tracking (links route through Send and record clicks, 302 only to the stored URL), and receiving (mail to unassigned addresses lands in your workspace, see Receiving). Tracking is applied before the message is DKIM signed, so signatures always verify.

GET/email-domainsemails:read

List sendable domains

The domains your account currently holds send access on (verified domains only).

Request
curl -X GET https://api.dbrij.com/api/email-domains \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "d1a2…", "domain": "acme.com", "status": "active", "organizationId": "o3b4…" } ]
}

Sending email

The transactional rail: one call, one email, a timeline and a webhook trail. Suppressed recipients are dropped before anything sends: an email whose every recipient is suppressed never relays and is never billed.

POST/emailsemails:send

Send an email

Send one email (or schedule it with a future scheduledAt). Your API key is bound to the address it sends as, so from can be omitted entirely. Supports an Idempotency-Key header, see below.

PATH / BODY PARAMETERS

fromstringOptional: your key already knows its sender address. When given, it must match the key's address ("Name <addr@domain>" adds a display name; a bare address gets the domain's name, so hello@ricuit.com arrives as Ricuit).
to*string | string[]Recipient address(es). Max 50 recipients total across to/cc/bcc.
ccstring[]Carbon copy recipients.
bccstring[]Blind carbon copy recipients.
replyTostringReply-To address.
subjectstringSubject line (single line, max 998 chars). Required unless a templateId supplies it.
htmlstringHTML body. Provide html or text (or both), or a templateId.
textstringPlain text body.
templateIdstringRender a saved template as the body; explicit subject/html/text win over it.
variablesobjectValues for the template's {{merge tags}}.
headersobjectUp to 10 custom headers. Structural headers (From, To, Subject, Content-Type, …) are rejected.
attachmentsAttachment[]Up to 10, 10MB total decoded. Each: { filename, content? (base64), url? (https), contentType? }. See Attachments below.
scheduledAtstring (ISO-8601)A future time schedules the send instead of sending now.
Request
curl -X POST https://api.dbrij.com/api/emails \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "Acme <no-reply@acme.com>",
  "to": ["jane@example.com"],
  "subject": "Welcome to Acme",
  "html": "<h1>Welcome!</h1><p>Glad to have you.</p>",
  "text": "Welcome! Glad to have you."
}'
Request body
{
  "from": "Acme <no-reply@acme.com>",
  "to": ["jane@example.com"],
  "subject": "Welcome to Acme",
  "html": "<h1>Welcome!</h1><p>Glad to have you.</p>",
  "text": "Welcome! Glad to have you."
}
Response 200
{
  "success": true,
  "data": {
    "id": "e5d3…",
    "from": "Acme <no-reply@acme.com>",
    "to": ["jane@example.com"],
    "cc": [],
    "bcc": [],
    "replyTo": null,
    "subject": "Welcome to Acme",
    "status": "sent",
    "scheduledAt": null,
    "sentAt": "2026-07-01T09:00:00.000Z",
    "deliveredAt": null,
    "messageId": "<a1b2…@acme.com>",
    "lastError": null,
    "sandbox": false,
    "createdAt": "2026-07-01T09:00:00.000Z"
  }
}
POST/emails/batchemails:send

Send a batch

Up to 100 sends in one call, each going out as your key's sender address (from may be omitted per item). Scheduling is not allowed in a batch. Results are per item. A failed item does not fail the batch. An Idempotency-Key covers the whole batch, per item under the hood.

Request
curl -X POST https://api.dbrij.com/api/emails/batch \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
  { "to": "jane@example.com", "subject": "Hi Jane", "text": "…" },
  { "to": "sam@example.com", "subject": "Hi Sam", "text": "…" }
]'
Request body
[
  { "to": "jane@example.com", "subject": "Hi Jane", "text": "…" },
  { "to": "sam@example.com", "subject": "Hi Sam", "text": "…" }
]
Response 200
{
  "success": true,
  "data": [
    { "id": "e5d3…", "status": "sent" },
    { "error": "Invalid to recipient: bob@" }
  ]
}
GET/emailsemails:read

List emails

Your workspace's sent emails, newest first.

QUERY PARAMETERS

limitnumberMax emails (1 to 100, default 20).
beforestringCursor: an ISO-8601 time or an email id. Returns emails created before it.
Request
curl -X GET https://api.dbrij.com/api/emails \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "e5d3…", "to": ["jane@example.com"], "subject": "Welcome to Acme", "status": "delivered", … } ]
}
GET/emails/:idemails:read

Get an email

Fetch one email, including its delivery status and any error.

PATH / BODY PARAMETERS

id*string (path)The email id.
Request
curl -X GET https://api.dbrij.com/api/emails/:id \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "id": "e5d3…", "status": "delivered", "deliveredAt": "2026-07-01T09:00:04.000Z", … }
}
DELETE/emails/:idemails:send

Cancel a scheduled email

Cancel a scheduled email before it fires. Only status "scheduled" can be cancelled.

PATH / BODY PARAMETERS

id*string (path)The email id.
Request
curl -X DELETE https://api.dbrij.com/api/emails/:id \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "id": "e5d3…", "status": "cancelled", … }
}
GET/emails/:id/eventsemails:read

Get an email's timeline

Every event the email produced, in order: queued, sent, delivered, opened, clicked, bounced, complained.

PATH / BODY PARAMETERS

id*string (path)The email id.
Request
curl -X GET https://api.dbrij.com/api/emails/:id/events \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "ev1…", "type": "delivered", "recipient": "jane@example.com", "createdAt": "…" },
    { "id": "ev2…", "type": "opened", "createdAt": "…" } ]
}

Idempotency

Pass an Idempotency-Key header (max 190 chars) on POST /emails. Retrying with the same key returns the original email instead of sending a duplicate. On POST /emails/batch one key (max 180 chars) covers the whole batch, per item under the hood: a retried batch skips what already landed and finishes what did not.

Idempotent send
curl -X POST https://api.dbrij.com/api/emails \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: welcome-user-42" \
  -d '{ "to": "jane@example.com",
        "subject": "Welcome to Acme", "text": "Hi Jane!" }'

Scheduling

Set scheduledAt to a future ISO-8601 time and the email is queued instead of sent (status scheduled). Cancel it any time before it fires with DELETE /emails/:id. Scheduling is not available in /emails/batch, and send access is checked again at fire time: access revoked between scheduling and sending fails the send.

Attachments

ATTACHMENT FIELDS

filename*stringFile name (max 255 chars).
contentstring (base64)Inline file body. Provide content or url.
urlstring (https)Public https URL fetched on our servers at send time.
contentTypestringMIME type, e.g. "application/pdf".

Up to 10 attachments per email, 10MB total (decoded).

Templates

A template is a versioned body with {{variable}} merge tags. One template serves all three rails: transactional sends (templateId + variables on POST /emails), broadcasts, and automation steps. Contact fields (firstName, lastName, email, custom fields) fill the tags automatically on broadcasts and automations.

POST/templatestemplates:write

Create a template

A reusable body with {{variable}} merge tags, detected automatically. Send with it by passing templateId + variables to POST /emails, or reference it from broadcasts and automation steps. Every save appends a version. Instead of html you can pass a design from the template library (layout, palette, typography, header and your copy, as the dashboard saves it): the HTML renders server side and the template stays editable as a form.

Request
curl -X POST https://api.dbrij.com/api/templates \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Welcome", "subject": "Hello {{firstName}}", "html": "<p>Hi {{firstName}}, welcome aboard.</p>" }
// or, from the library:
{ "name": "Weekly", "subject": "This week at Acme", "design": { "layout": "weekly", "palette": "ocean", "typography": "modern", "header": "band", "content": { "companyName": "Acme", "title": "…" } } }'
Request body
{ "name": "Welcome", "subject": "Hello {{firstName}}", "html": "<p>Hi {{firstName}}, welcome aboard.</p>" }
// or, from the library:
{ "name": "Weekly", "subject": "This week at Acme", "design": { "layout": "weekly", "palette": "ocean", "typography": "modern", "header": "band", "content": { "companyName": "Acme", "title": "…" } } }
Response 200
{
  "success": true,
  "data": { "id": "t1a2…", "name": "Welcome", "subject": "Hello {{firstName}}", "variables": ["firstName"], "currentVersion": 1, … }
}
GET/templatesemails:read

List templates

Every template in the workspace, newest first.

Request
curl -X GET https://api.dbrij.com/api/templates \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "t1a2…", "name": "Welcome", "variables": ["firstName"], "currentVersion": 3, … } ]
}
GET/templates/:idemails:read

Get a template

One template with its full body.

PATH / BODY PARAMETERS

id*string (path)The template id.
Request
curl -X GET https://api.dbrij.com/api/templates/:id \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "id": "t1a2…", "name": "Welcome", "html": "<p>…</p>", "text": null, … }
}
PATCH/templates/:idtemplates:write

Update a template

Save a new version. Emails already sent keep the version they rendered from.

PATH / BODY PARAMETERS

id*string (path)The template id.
Request
curl -X PATCH https://api.dbrij.com/api/templates/:id \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "subject": "Hello {{firstName}} 👋" }'
Request body
{ "subject": "Hello {{firstName}} 👋" }
Response 200
{
  "success": true,
  "data": { "id": "t1a2…", "currentVersion": 4, … }
}
DELETE/templates/:idtemplates:write

Delete a template

Removes the template. Automation steps that reference it stop sending.

PATH / BODY PARAMETERS

id*string (path)The template id.
Request
curl -X DELETE https://api.dbrij.com/api/templates/:id \
  -H "Authorization: Bearer $DBRIJ_API_KEY"

Returns 204 (no body).

Audiences and contacts

An audience is a contact list. Broadcasts send to one; automations can trigger on someone joining one. A contact who unsubscribes is marked across every audience in the workspace and suppressed, so nothing sends to them again.

POST/audiencesaudiences:write

Create an audience

A contact list for broadcasts and automations.

Request
curl -X POST https://api.dbrij.com/api/audiences \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Newsletter" }'
Request body
{ "name": "Newsletter" }
Response 200
{
  "success": true,
  "data": { "id": "a1b2…", "name": "Newsletter", "contactCount": 0, … }
}
GET/audiencesemails:read

List audiences

Every audience with its live contact count.

Request
curl -X GET https://api.dbrij.com/api/audiences \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "a1b2…", "name": "Newsletter", "contactCount": 1240, … } ]
}
GET/audiences/:id/contactsemails:read

List contacts

The audience's contacts, newest first.

PATH / BODY PARAMETERS

id*string (path)The audience id.

QUERY PARAMETERS

limitnumberMax contacts (default 50).
beforestring (ISO-8601)Return contacts created before this time.
Request
curl -X GET https://api.dbrij.com/api/audiences/:id/contacts \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "c1a2…", "email": "jane@example.com", "firstName": "Jane", "unsubscribed": false, … } ]
}
POST/audiences/:id/contactsaudiences:write

Add a contact

Adding a contact fires contact.created and can trigger a contact.added automation. The same email joins an audience once; adding again updates the fields.

PATH / BODY PARAMETERS

id*string (path)The audience id.
Request
curl -X POST https://api.dbrij.com/api/audiences/:id/contacts \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "jane@example.com", "firstName": "Jane", "lastName": "Doe", "fields": { "plan": "pro" } }'
Request body
{ "email": "jane@example.com", "firstName": "Jane", "lastName": "Doe", "fields": { "plan": "pro" } }
Response 200
{
  "success": true,
  "data": { "id": "c1a2…", "email": "jane@example.com", "firstName": "Jane", … }
}
PATCH/audiences/:id/contacts/:contactIdaudiences:write

Update a contact

Change names, custom fields, or the unsubscribed flag.

PATH / BODY PARAMETERS

id*string (path)The audience id.
contactId*string (path)The contact id.
Request
curl -X PATCH https://api.dbrij.com/api/audiences/:id/contacts/:contactId \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "fields": { "plan": "scale" } }'
Request body
{ "fields": { "plan": "scale" } }
Response 200
{
  "success": true,
  "data": { "id": "c1a2…", "fields": { "plan": "scale" }, … }
}
POST/audiences/:id/contacts/importaudiences:write

Import contacts

Bulk upsert up to 10,000 contacts in one call. Existing emails are updated, new ones created; the result counts both.

PATH / BODY PARAMETERS

id*string (path)The audience id.
Request
curl -X POST https://api.dbrij.com/api/audiences/:id/contacts/import \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contacts": [ { "email": "jane@example.com", "firstName": "Jane" }, { "email": "sam@example.com" } ] }'
Request body
{ "contacts": [ { "email": "jane@example.com", "firstName": "Jane" }, { "email": "sam@example.com" } ] }
Response 200
{
  "success": true,
  "data": { "created": 1, "updated": 1, "skipped": 0 }
}
DELETE/audiences/:id/contacts/:contactIdaudiences:write

Remove a contact

Removes the contact from this audience (their suppression state, if any, is untouched).

PATH / BODY PARAMETERS

id*string (path)The audience id.
contactId*string (path)The contact id.
Request
curl -X DELETE https://api.dbrij.com/api/audiences/:id/contacts/:contactId \
  -H "Authorization: Bearer $DBRIJ_API_KEY"

Returns 204 (no body).

Broadcasts

One message to a whole audience, through the same pipeline as transactional mail, so every recipient gets a real email row with tracking and a timeline. The body freezes when sending starts; batches go out at a steady pace; and sending halts itself when bounce or complaint rates spike, because a burning list costs the domain more than the campaign is worth. Every message carries a working one click unsubscribe.

POST/broadcastsbroadcasts:send

Create a broadcast

One message to a whole audience through the same pipeline as transactional mail: every recipient gets a real email row with its own timeline. Compose with a templateId or inline html.

Request
curl -X POST https://api.dbrij.com/api/broadcasts \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "August update", "audienceId": "a1b2…", "fromEmail": "news@acme.com", "subject": "What is new", "html": "<p>Hi {{firstName}},…</p>" }'
Request body
{ "name": "August update", "audienceId": "a1b2…", "fromEmail": "news@acme.com", "subject": "What is new", "html": "<p>Hi {{firstName}},…</p>" }
Response 200
{
  "success": true,
  "data": { "id": "b1c2…", "status": "draft", "totals": { "recipients": 0, … }, … }
}
POST/broadcasts/:id/sendbroadcasts:send

Send or schedule it

Freezes the body, snapshots the audience, and starts sending in paced batches (or schedules for a future scheduledAt). Suppressed and unsubscribed contacts are skipped; an unsubscribe link is added to every message; sending halts itself when bounces or complaints spike.

PATH / BODY PARAMETERS

id*string (path)The broadcast id.
Request
curl -X POST https://api.dbrij.com/api/broadcasts/:id/send \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "scheduledAt": "2026-08-20T09:00:00.000Z" }'
Request body
{ "scheduledAt": "2026-08-20T09:00:00.000Z" }
Response 200
{
  "success": true,
  "data": { "id": "b1c2…", "status": "scheduled", "scheduledAt": "2026-08-20T09:00:00.000Z", … }
}
GET/broadcasts/:idemails:read

Get a broadcast

Live totals while sending and after: recipients, sent, delivered, bounced, complained, opened, clicked, unsubscribed, skipped.

PATH / BODY PARAMETERS

id*string (path)The broadcast id.
Request
curl -X GET https://api.dbrij.com/api/broadcasts/:id \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "id": "b1c2…", "status": "sent", "totals": { "recipients": 1200, "sent": 1188, "opened": 480, … }, … }
}
POST/broadcasts/:id/cancelbroadcasts:send

Cancel a broadcast

Stops a scheduled broadcast, or a sending one where it stands. Recipients already sent stay sent.

PATH / BODY PARAMETERS

id*string (path)The broadcast id.
Request
curl -X POST https://api.dbrij.com/api/broadcasts/:id/cancel \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "id": "b1c2…", "status": "canceled", … }
}

Automations

A trigger and a straight line of steps. Someone joins an audience (or opens, clicks or receives an email), the automation waits a day, then sends the next template. Each address is enrolled at most once per automation, ever (triggering again never re enrolls), and a suppressed address's run is cancelled before it sends.

POST/automationsautomations:write

Create an automation

A trigger plus LINEAR wait/send steps (at most 20; waits between one minute and thirty days). Triggers: a contact joining an audience, or an email event (opened, clicked, delivered). Each address is enrolled at most once per automation, ever.

Request
curl -X POST https://api.dbrij.com/api/automations \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Welcome series", "trigger": { "type": "contact.added", "audienceId": "a1b2…" },
  "steps": [ { "type": "send", "templateId": "t1a2…", "fromEmail": "hello@acme.com" },
             { "type": "wait", "durationMs": 86400000 },
             { "type": "send", "templateId": "t9z8…", "fromEmail": "hello@acme.com" } ] }'
Request body
{ "name": "Welcome series", "trigger": { "type": "contact.added", "audienceId": "a1b2…" },
  "steps": [ { "type": "send", "templateId": "t1a2…", "fromEmail": "hello@acme.com" },
             { "type": "wait", "durationMs": 86400000 },
             { "type": "send", "templateId": "t9z8…", "fromEmail": "hello@acme.com" } ] }
Response 200
{
  "success": true,
  "data": { "id": "au1…", "status": "draft", "enrolledCount": 0, … }
}
POST/automations/:id/enableautomations:write

Enable or pause

An automation only enrolls while active. Pausing holds running enrollments where they stand; enabling resumes them.

PATH / BODY PARAMETERS

id*string (path)The automation id.
Request
curl -X POST https://api.dbrij.com/api/automations/:id/enable \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'
Request body
{ "enabled": true }
Response 200
{
  "success": true,
  "data": { "id": "au1…", "status": "active", … }
}
GET/automationsemails:read

List automations

Every automation with its enrolled count. Also GET/PATCH/DELETE /automations/:id.

Request
curl -X GET https://api.dbrij.com/api/automations \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "au1…", "name": "Welcome series", "status": "active", "enrolledCount": 214, … } ]
}

Suppressions

The workspace's do not email list, checked before every send on every rail. Hard bounces, spam complaints and unsubscribes are added automatically; you can add and remove addresses yourself. Suppression wins before quota: a dropped recipient is never billed.

POST/suppressionssuppressions:write

Suppress addresses

Add addresses to the do not email list every send checks. Hard bounces, spam complaints and unsubscribes land here automatically; this endpoint is for your own removals.

Request
curl -X POST https://api.dbrij.com/api/suppressions \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "emails": ["gone@example.com"], "note": "asked to be removed" }'
Request body
{ "emails": ["gone@example.com"], "note": "asked to be removed" }
Response 200
{
  "success": true,
  "data": { "added": 1 }
}
GET/suppressionsemails:read

List suppressions

The workspace suppression list with each address's reason: unsubscribed, bounced, complained or manual.

QUERY PARAMETERS

limitnumberMax rows (default 50).
beforestring (ISO-8601)Return rows created before this time.
Request
curl -X GET https://api.dbrij.com/api/suppressions \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "email": "gone@example.com", "reason": "manual", "note": "asked to be removed", "createdAt": "…" } ]
}
DELETE/suppressions/:emailsuppressions:write

Unsuppress an address

Remove one address from the list. Think twice about unsuppressing a bounce or a complaint: the next one costs reputation.

PATH / BODY PARAMETERS

email*string (path)The address to remove.
Request
curl -X DELETE https://api.dbrij.com/api/suppressions/:email \
  -H "Authorization: Bearer $DBRIJ_API_KEY"

Returns 204 (no body).

Receiving

Turn receiving on for a domain (Domains page) and mail sent to any address on it that has no company mailbox lands in your workspace: stored, listed here, and echoed to your app as an email.received webhook. Company mailboxes always resolve first, so receiving can never shadow a real inbox.

GET/inboundinbound:read

List received email

Email received on a domain with receiving turned on, newest first. Each arrival also fires an email.received webhook.

QUERY PARAMETERS

limitnumberMax rows (default 50).
beforestring (ISO-8601)Return rows created before this time.
Request
curl -X GET https://api.dbrij.com/api/inbound \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "in1…", "fromAddress": "customer@example.com", "to": ["anything@acme.com"], "subject": "Hi", … } ]
}
GET/inbound/:idinbound:read

Get a received email

The full message: html and text bodies, headers, authentication results and attachments (base64).

PATH / BODY PARAMETERS

id*string (path)The inbound email id.
Request
curl -X GET https://api.dbrij.com/api/inbound/:id \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "id": "in1…", "fromAddress": "customer@example.com", "html": "<p>…</p>", "attachments": [ { "filename": "invoice.pdf", … } ], … }
}

Stats

The numbers behind the dashboard Metrics page: totals and rates over a window, plus a per day series for charts.

GET/statsemails:read

Sending stats

Aggregate counts and rates over your workspace, the dashboard Metrics page over HTTP.

QUERY PARAMETERS

daysnumberThe window, 1 to 90 (default 30).
Request
curl -X GET https://api.dbrij.com/api/stats \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "from": "2026-07-15", "to": "2026-08-14", "totals": { "sent": 12480, "delivered": 12333, … }, "deliveryRate": 0.988, "openRate": 0.41, …, "series": [ … ] }
}

Webhooks

Send POSTs a signed JSON envelope to your endpoints for each event. Register as many endpoints as your plan allows, each with its own secret and event filter. Deliveries are retried three times, logged, and replayable; an endpoint failing 20 deliveries in a row is paused (and the owner emailed) rather than silently dropped forever.

Envelope
{
  "id": "evt_…",
  "type": "email.delivered",
  "createdAt": "2026-07-01T09:00:04.000Z",
  "data": { … }
}
POST/webhookswebhooks:manage

Add a webhook endpoint

Send supports MANY endpoints, each with its own whsec_ secret (returned once) and an event filter (empty = every event). After 20 consecutive delivery failures an endpoint is paused and the owner emailed; fix it and enable it again.

Request
curl -X POST https://api.dbrij.com/api/webhooks \
  -H "Authorization: Bearer $DBRIJ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://api.yourapp.com/webhooks/dbrij", "events": ["email.delivered", "email.bounced"] }'
Request body
{ "url": "https://api.yourapp.com/webhooks/dbrij", "events": ["email.delivered", "email.bounced"] }
Response 200
{
  "success": true,
  "data": { "id": "w1a2…", "url": "https://…", "secret": "whsec_…", "events": ["email.delivered", "email.bounced"], … }
}
GET/webhooksemails:read

List endpoints

Every endpoint with its status and failure streak. Also PATCH/DELETE /webhooks/:id and POST /webhooks/:id/rotate-secret.

Request
curl -X GET https://api.dbrij.com/api/webhooks \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "w1a2…", "url": "https://…", "status": "enabled", "consecutiveFailures": 0, … } ]
}
GET/webhooks/deliveriesemails:read

The delivery log

Every attempted delivery: status code, attempts, duration and error. Filter with ?endpointId=.

Request
curl -X GET https://api.dbrij.com/api/webhooks/deliveries \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": [ { "id": "d1…", "event": "email.delivered", "statusCode": 200, "ok": true, "attempts": 1, "durationMs": 84, … } ]
}
POST/webhooks/deliveries/:deliveryId/replaywebhooks:manage

Replay a delivery

Queues the exact logged payload to its endpoint again, signed fresh at delivery time.

PATH / BODY PARAMETERS

deliveryId*string (path)The delivery id from the log.
Request
curl -X POST https://api.dbrij.com/api/webhooks/deliveries/:deliveryId/replay \
  -H "Authorization: Bearer $DBRIJ_API_KEY"
Response 200
{
  "success": true,
  "data": { "queued": true }
}

Events

email.sentAn email was handed to the mail transport.
data
{ "emailId": "e5d3…", "from": "Acme <no-reply@acme.com>", "to": ["jane@example.com"], "subject": "Welcome to Acme" }
email.deliveredA recipient's mail server accepted the email.
data
{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…", "recipient": "jane@example.com" }
email.failedA send or a delivery failed (carries the reason).
data
{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…", "reason": "550 mailbox unavailable", "recipient": "jane@example.com" }
email.bouncedA recipient hard bounced (the address is auto suppressed).
data
{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…", "reason": "550 mailbox unavailable", "recipient": "jane@example.com" }
email.complainedA recipient marked the email as spam (auto suppressed).
data
{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…" }
email.openedA tracked email was opened (open tracking on).
data
{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…" }
email.clickedA tracked link was clicked (click tracking on).
data
{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…", "url": "https://acme.com/x" }
email.receivedInbound mail arrived on a receiving enabled domain.
data
{ "inboundId": "in1…", "from": "customer@example.com", "to": ["anything@acme.com"], "subject": "Hi" }
contact.createdA contact joined one of your audiences.
data
{ "contactId": "c1a2…", "audienceId": "a1b2…", "email": "jane@example.com", "unsubscribed": false }
contact.unsubscribedA contact unsubscribed (also suppressed workspace wide).
data
{ "email": "jane@example.com" }
broadcast.sentA broadcast finished sending, with its totals.
data
{ "broadcastId": "b1c2…", "name": "August update", "totals": { "recipients": 1200, "sent": 1188, … } }
broadcast.haltedA broadcast stopped itself (bounce or complaint rate, or a plan limit).
data
{ "broadcastId": "b1c2…", "reason": "Stopped at 6% bounces…" }

Verify the signature

Each delivery carries X-Dbrij-Signature: sha256=…, an HMAC of the raw request body using the endpoint's whsec_ secret, and X-Dbrij-Signature-V2: t=…,sha256=…, an HMAC of `${t}.${body}` for replay protection. Verify one of them before trusting a payload.

Node
import { createHmac } from 'crypto';

function verify(rawBody, header, secret) {
  const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
  return header === expected; // compare to X-Dbrij-Signature
}

function verifyV2(rawBody, header, secret, toleranceSec = 300) {
  const [tPart, sigPart] = header.split(',');            // "t=1690000000,sha256=…"
  const t = tPart.slice(2);
  if (Math.abs(Date.now() / 1000 - Number(t)) > toleranceSec) return false;
  const expected = 'sha256=' + createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex');
  return sigPart === expected;
}

Plans, errors and limits

Send bills by monthly email volume, never per seat. Every account starts free; paid plans bill overage per extra thousand at renewal, from the closed month's usage. The free plan is a hard stop instead of a bill.

PlanMonthlyEmails / monthOverage / 1,000ContactsDomainsRequests / minWebhook endpointsRetention
FreeFree3,000 (100 a day)Hard stop1,00016003 days
Launch₦12,000 / mo15,000₦1,8005,0003300514 days
Starter₦40,000 / mo100,000₦1,50025,000106001030 days
Growth₦90,000 / mo200,000₦1,300100,000501,2002560 days
Scale₦270,000 / mo1,000,000₦1,000500,0002003,00010090 days

Rate limits

Every request counts toward your plan's per minute ceiling. Each response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 adds Retry-After in seconds. New paid workspaces also ramp daily volume for the first two weeks, because deliverability lost is months to win back.

Errors

401UnauthorizedMissing, invalid, revoked or expired API key.
403ForbiddenKey missing a required scope, or sending as an address it is not bound to.
404Not FoundUnknown email, template, audience, broadcast or automation.
402Payment RequiredMonthly volume exhausted on the free plan. Upgrade in the dashboard.
429Too Many RequestsPer minute rate ceiling, or the free plan's daily cap.
422 / 400ValidationMalformed body or invalid field.
Error shape
{
  "success": false,
  "statusCode": 403,
  "message": "This key sends as billing@acme.com. Use that from address, or omit from entirely.",
  "error": "Forbidden",
  "path": "/api/v1/emails",
  "timestamp": "2026-08-14T22:56:17.969Z"
}

Dbrij is Nigeria’s company operating system: the first Nigerian built platform to put team chat, video meetings, email, HR, tax compliant payroll, customer support, marketing, analytics and cloud hosting in one product on one subscription.

Everything on Dbrij

More from Dbrij