Everything you need to implement email with Dbrij Send: domains, sending, templates, audiences, broadcasts, automations, suppressions, receiving, webhooks and limits.
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.
https://api.dbrij.com/apiEvery 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).
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.
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.
Authenticate every request with an API key from the Send dashboard, sent as a Bearer token.
Authorization: Bearer dbrij_live_xxxxxxxxxxxxxxxxxxxxxxxxA 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:send | scope | Send, schedule and cancel emails. |
| emails:read | scope | Read emails, timelines, domains, stats and every list. |
| templates:write | scope | Create and edit templates. |
| audiences:write | scope | Manage audiences and contacts. |
| broadcasts:send | scope | Create, send and cancel broadcasts. |
| automations:write | scope | Create and manage automations. |
| suppressions:write | scope | Add and remove suppressions. |
| webhooks:manage | scope | Manage webhook endpoints and replay deliveries. |
| inbound:read | scope | Read received email. |
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.
/email-domainsemails:readList sendable domains
The domains your account currently holds send access on (verified domains only).
curl -X GET https://api.dbrij.com/api/email-domains \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "d1a2…", "domain": "acme.com", "status": "active", "organizationId": "o3b4…" } ]
}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.
/emailsemails:sendSend 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
| from | string | Optional: 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. |
| cc | string[] | Carbon copy recipients. |
| bcc | string[] | Blind carbon copy recipients. |
| replyTo | string | Reply-To address. |
| subject | string | Subject line (single line, max 998 chars). Required unless a templateId supplies it. |
| html | string | HTML body. Provide html or text (or both), or a templateId. |
| text | string | Plain text body. |
| templateId | string | Render a saved template as the body; explicit subject/html/text win over it. |
| variables | object | Values for the template's {{merge tags}}. |
| headers | object | Up to 10 custom headers. Structural headers (From, To, Subject, Content-Type, …) are rejected. |
| attachments | Attachment[] | Up to 10, 10MB total decoded. Each: { filename, content? (base64), url? (https), contentType? }. See Attachments below. |
| scheduledAt | string (ISO-8601) | A future time schedules the send instead of sending now. |
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."
}'{
"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."
}{
"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"
}
}/emails/batchemails:sendSend 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.
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": "…" }
]'[
{ "to": "jane@example.com", "subject": "Hi Jane", "text": "…" },
{ "to": "sam@example.com", "subject": "Hi Sam", "text": "…" }
]{
"success": true,
"data": [
{ "id": "e5d3…", "status": "sent" },
{ "error": "Invalid to recipient: bob@" }
]
}/emailsemails:readList emails
Your workspace's sent emails, newest first.
QUERY PARAMETERS
| limit | number | Max emails (1 to 100, default 20). |
| before | string | Cursor: an ISO-8601 time or an email id. Returns emails created before it. |
curl -X GET https://api.dbrij.com/api/emails \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "e5d3…", "to": ["jane@example.com"], "subject": "Welcome to Acme", "status": "delivered", … } ]
}/emails/:idemails:readGet an email
Fetch one email, including its delivery status and any error.
PATH / BODY PARAMETERS
| id* | string (path) | The email id. |
curl -X GET https://api.dbrij.com/api/emails/:id \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "id": "e5d3…", "status": "delivered", "deliveredAt": "2026-07-01T09:00:04.000Z", … }
}/emails/:idemails:sendCancel 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. |
curl -X DELETE https://api.dbrij.com/api/emails/:id \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "id": "e5d3…", "status": "cancelled", … }
}/emails/:id/eventsemails:readGet 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. |
curl -X GET https://api.dbrij.com/api/emails/:id/events \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "ev1…", "type": "delivered", "recipient": "jane@example.com", "createdAt": "…" },
{ "id": "ev2…", "type": "opened", "createdAt": "…" } ]
}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.
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!" }'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.
ATTACHMENT FIELDS
| filename* | string | File name (max 255 chars). |
| content | string (base64) | Inline file body. Provide content or url. |
| url | string (https) | Public https URL fetched on our servers at send time. |
| contentType | string | MIME type, e.g. "application/pdf". |
Up to 10 attachments per email, 10MB total (decoded).
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.
/templatestemplates:writeCreate 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.
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": "…" } } }'{ "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": "…" } } }{
"success": true,
"data": { "id": "t1a2…", "name": "Welcome", "subject": "Hello {{firstName}}", "variables": ["firstName"], "currentVersion": 1, … }
}/templatesemails:readList templates
Every template in the workspace, newest first.
curl -X GET https://api.dbrij.com/api/templates \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "t1a2…", "name": "Welcome", "variables": ["firstName"], "currentVersion": 3, … } ]
}/templates/:idemails:readGet a template
One template with its full body.
PATH / BODY PARAMETERS
| id* | string (path) | The template id. |
curl -X GET https://api.dbrij.com/api/templates/:id \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "id": "t1a2…", "name": "Welcome", "html": "<p>…</p>", "text": null, … }
}/templates/:idtemplates:writeUpdate a template
Save a new version. Emails already sent keep the version they rendered from.
PATH / BODY PARAMETERS
| id* | string (path) | The template id. |
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}} 👋" }'{ "subject": "Hello {{firstName}} 👋" }{
"success": true,
"data": { "id": "t1a2…", "currentVersion": 4, … }
}/templates/:idtemplates:writeDelete a template
Removes the template. Automation steps that reference it stop sending.
PATH / BODY PARAMETERS
| id* | string (path) | The template id. |
curl -X DELETE https://api.dbrij.com/api/templates/:id \
-H "Authorization: Bearer $DBRIJ_API_KEY"Returns 204 (no body).
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.
/audiencesaudiences:writeCreate an audience
A contact list for broadcasts and automations.
curl -X POST https://api.dbrij.com/api/audiences \
-H "Authorization: Bearer $DBRIJ_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Newsletter" }'{ "name": "Newsletter" }{
"success": true,
"data": { "id": "a1b2…", "name": "Newsletter", "contactCount": 0, … }
}/audiencesemails:readList audiences
Every audience with its live contact count.
curl -X GET https://api.dbrij.com/api/audiences \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "a1b2…", "name": "Newsletter", "contactCount": 1240, … } ]
}/audiences/:id/contactsemails:readList contacts
The audience's contacts, newest first.
PATH / BODY PARAMETERS
| id* | string (path) | The audience id. |
QUERY PARAMETERS
| limit | number | Max contacts (default 50). |
| before | string (ISO-8601) | Return contacts created before this time. |
curl -X GET https://api.dbrij.com/api/audiences/:id/contacts \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "c1a2…", "email": "jane@example.com", "firstName": "Jane", "unsubscribed": false, … } ]
}/audiences/:id/contactsaudiences:writeAdd 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. |
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" } }'{ "email": "jane@example.com", "firstName": "Jane", "lastName": "Doe", "fields": { "plan": "pro" } }{
"success": true,
"data": { "id": "c1a2…", "email": "jane@example.com", "firstName": "Jane", … }
}/audiences/:id/contacts/:contactIdaudiences:writeUpdate 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. |
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" } }'{ "fields": { "plan": "scale" } }{
"success": true,
"data": { "id": "c1a2…", "fields": { "plan": "scale" }, … }
}/audiences/:id/contacts/importaudiences:writeImport 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. |
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" } ] }'{ "contacts": [ { "email": "jane@example.com", "firstName": "Jane" }, { "email": "sam@example.com" } ] }{
"success": true,
"data": { "created": 1, "updated": 1, "skipped": 0 }
}/audiences/:id/contacts/:contactIdaudiences:writeRemove 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. |
curl -X DELETE https://api.dbrij.com/api/audiences/:id/contacts/:contactId \
-H "Authorization: Bearer $DBRIJ_API_KEY"Returns 204 (no body).
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.
/broadcastsbroadcasts:sendCreate 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.
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>" }'{ "name": "August update", "audienceId": "a1b2…", "fromEmail": "news@acme.com", "subject": "What is new", "html": "<p>Hi {{firstName}},…</p>" }{
"success": true,
"data": { "id": "b1c2…", "status": "draft", "totals": { "recipients": 0, … }, … }
}/broadcasts/:id/sendbroadcasts:sendSend 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. |
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" }'{ "scheduledAt": "2026-08-20T09:00:00.000Z" }{
"success": true,
"data": { "id": "b1c2…", "status": "scheduled", "scheduledAt": "2026-08-20T09:00:00.000Z", … }
}/broadcasts/:idemails:readGet 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. |
curl -X GET https://api.dbrij.com/api/broadcasts/:id \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "id": "b1c2…", "status": "sent", "totals": { "recipients": 1200, "sent": 1188, "opened": 480, … }, … }
}/broadcasts/:id/cancelbroadcasts:sendCancel 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. |
curl -X POST https://api.dbrij.com/api/broadcasts/:id/cancel \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "id": "b1c2…", "status": "canceled", … }
}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.
/automationsautomations:writeCreate 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.
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" } ] }'{ "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" } ] }{
"success": true,
"data": { "id": "au1…", "status": "draft", "enrolledCount": 0, … }
}/automations/:id/enableautomations:writeEnable 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. |
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 }'{ "enabled": true }{
"success": true,
"data": { "id": "au1…", "status": "active", … }
}/automationsemails:readList automations
Every automation with its enrolled count. Also GET/PATCH/DELETE /automations/:id.
curl -X GET https://api.dbrij.com/api/automations \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "au1…", "name": "Welcome series", "status": "active", "enrolledCount": 214, … } ]
}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.
/suppressionssuppressions:writeSuppress 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.
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" }'{ "emails": ["gone@example.com"], "note": "asked to be removed" }{
"success": true,
"data": { "added": 1 }
}/suppressionsemails:readList suppressions
The workspace suppression list with each address's reason: unsubscribed, bounced, complained or manual.
QUERY PARAMETERS
| limit | number | Max rows (default 50). |
| before | string (ISO-8601) | Return rows created before this time. |
curl -X GET https://api.dbrij.com/api/suppressions \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "email": "gone@example.com", "reason": "manual", "note": "asked to be removed", "createdAt": "…" } ]
}/suppressions/:emailsuppressions:writeUnsuppress 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. |
curl -X DELETE https://api.dbrij.com/api/suppressions/:email \
-H "Authorization: Bearer $DBRIJ_API_KEY"Returns 204 (no body).
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.
/inboundinbound:readList received email
Email received on a domain with receiving turned on, newest first. Each arrival also fires an email.received webhook.
QUERY PARAMETERS
| limit | number | Max rows (default 50). |
| before | string (ISO-8601) | Return rows created before this time. |
curl -X GET https://api.dbrij.com/api/inbound \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "in1…", "fromAddress": "customer@example.com", "to": ["anything@acme.com"], "subject": "Hi", … } ]
}/inbound/:idinbound:readGet 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. |
curl -X GET https://api.dbrij.com/api/inbound/:id \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "id": "in1…", "fromAddress": "customer@example.com", "html": "<p>…</p>", "attachments": [ { "filename": "invoice.pdf", … } ], … }
}The numbers behind the dashboard Metrics page: totals and rates over a window, plus a per day series for charts.
/statsemails:readSending stats
Aggregate counts and rates over your workspace, the dashboard Metrics page over HTTP.
QUERY PARAMETERS
| days | number | The window, 1 to 90 (default 30). |
curl -X GET https://api.dbrij.com/api/stats \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "from": "2026-07-15", "to": "2026-08-14", "totals": { "sent": 12480, "delivered": 12333, … }, "deliveryRate": 0.988, "openRate": 0.41, …, "series": [ … ] }
}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.
{
"id": "evt_…",
"type": "email.delivered",
"createdAt": "2026-07-01T09:00:04.000Z",
"data": { … }
}/webhookswebhooks:manageAdd 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.
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"] }'{ "url": "https://api.yourapp.com/webhooks/dbrij", "events": ["email.delivered", "email.bounced"] }{
"success": true,
"data": { "id": "w1a2…", "url": "https://…", "secret": "whsec_…", "events": ["email.delivered", "email.bounced"], … }
}/webhooksemails:readList endpoints
Every endpoint with its status and failure streak. Also PATCH/DELETE /webhooks/:id and POST /webhooks/:id/rotate-secret.
curl -X GET https://api.dbrij.com/api/webhooks \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "w1a2…", "url": "https://…", "status": "enabled", "consecutiveFailures": 0, … } ]
}/webhooks/deliveriesemails:readThe delivery log
Every attempted delivery: status code, attempts, duration and error. Filter with ?endpointId=.
curl -X GET https://api.dbrij.com/api/webhooks/deliveries \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ { "id": "d1…", "event": "email.delivered", "statusCode": 200, "ok": true, "attempts": 1, "durationMs": 84, … } ]
}/webhooks/deliveries/:deliveryId/replaywebhooks:manageReplay 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. |
curl -X POST https://api.dbrij.com/api/webhooks/deliveries/:deliveryId/replay \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": { "queued": true }
}email.sentAn email was handed to the mail transport.{ "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.{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…", "recipient": "jane@example.com" }email.failedA send or a delivery failed (carries the reason).{ "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).{ "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).{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…" }email.openedA tracked email was opened (open tracking on).{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…" }email.clickedA tracked link was clicked (click tracking on).{ "emailId": "e5d3…", "to": ["jane@example.com"], "subject": "…", "url": "https://acme.com/x" }email.receivedInbound mail arrived on a receiving enabled domain.{ "inboundId": "in1…", "from": "customer@example.com", "to": ["anything@acme.com"], "subject": "Hi" }contact.createdA contact joined one of your audiences.{ "contactId": "c1a2…", "audienceId": "a1b2…", "email": "jane@example.com", "unsubscribed": false }contact.unsubscribedA contact unsubscribed (also suppressed workspace wide).{ "email": "jane@example.com" }broadcast.sentA broadcast finished sending, with its totals.{ "broadcastId": "b1c2…", "name": "August update", "totals": { "recipients": 1200, "sent": 1188, … } }broadcast.haltedA broadcast stopped itself (bounce or complaint rate, or a plan limit).{ "broadcastId": "b1c2…", "reason": "Stopped at 6% bounces…" }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.
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;
}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.
| Plan | Monthly | Emails / month | Overage / 1,000 | Contacts | Domains | Requests / min | Webhook endpoints | Retention |
|---|---|---|---|---|---|---|---|---|
| Free | Free | 3,000 (100 a day) | Hard stop | 1,000 | 1 | 60 | 0 | 3 days |
| Launch | ₦12,000 / mo | 15,000 | ₦1,800 | 5,000 | 3 | 300 | 5 | 14 days |
| Starter | ₦40,000 / mo | 100,000 | ₦1,500 | 25,000 | 10 | 600 | 10 | 30 days |
| Growth | ₦90,000 / mo | 200,000 | ₦1,300 | 100,000 | 50 | 1,200 | 25 | 60 days |
| Scale | ₦270,000 / mo | 1,000,000 | ₦1,000 | 500,000 | 200 | 3,000 | 100 | 90 days |
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.
| 401 | Unauthorized | Missing, invalid, revoked or expired API key. |
| 403 | Forbidden | Key missing a required scope, or sending as an address it is not bound to. |
| 404 | Not Found | Unknown email, template, audience, broadcast or automation. |
| 402 | Payment Required | Monthly volume exhausted on the free plan. Upgrade in the dashboard. |
| 429 | Too Many Requests | Per minute rate ceiling, or the free plan's daily cap. |
| 422 / 400 | Validation | Malformed body or invalid field. |
{
"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.