Base URL
https://app.dmu.email/api/v1
Authentication
Bearer dmk_… API key
Rate limit
120 requests a minute per key

Manage webhooks

Make, change and remove webhooks through the API, with two limits that keep a leaked key from setting up something that outlives it.

The limits

  • A webhook made with a key is that key’s. The key lists, changes and deletes only the webhooks it made, and they stop for good when the key is revoked or expires.

  • It acts as the key’s person, and never carries more than the key could read itself: includeContent needs messages:read.

Endpoints

Endpoints

GET    /api/v1/webhooks                         webhooks:list    this key’s webhooks
POST   /api/v1/webhooks                         webhooks:manage  { "url", "events", "mailboxIds"?, "description"?, "includeContent"? }
GET    /api/v1/webhooks/{id}                    webhooks:list
PATCH  /api/v1/webhooks/{id}                    webhooks:manage  { "url"?, "events"?, "mailboxIds"?, "description"?, "includeContent"?, "status"? }
DELETE /api/v1/webhooks/{id}                    webhooks:manage  → 204, with its delivery log
POST   /api/v1/webhooks/{id}/secret             webhooks:manage  → the webhook with its new "secret"
POST   /api/v1/webhooks/{id}/test               webhooks:manage  → a webhook.test delivery, sent now, once
GET    /api/v1/webhooks/{id}/deliveries         webhooks:list    → the last 100
POST   /api/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver   webhooks:manage  → the same event again, now

A webhook

{ "data": {
  "id": "a950…", "url": "https://hooks.acme.gr/dmu", "description": "CRM sync",
  "events": ["message.received", "thread.assigned"], "mailboxIds": null, "includeContent": false,
  "secretHint": "FmnM", "previousSecretUntil": null,
  "status": "active", "disabledReason": null,
  "failingSince": null, "lastSuccessAt": "…", "lastFailureAt": null, "createdAt": "…"
} }

Some mailboxes only

mailboxIds narrows a webhook to events about conversations in those mailboxes, 1 to 200 of them. null, or leaving it out, is every mailbox its person can see. It only narrows: each mailbox must be one the person can see, and thread.moved matches the mailbox it left as well as the one it entered.

Status and errors

status is active, paused or disabled. disabledReason is failing (switch it back on with {"status": "active"} once it works), or owner_left or key_revoked, which are for good: make a new one.

Errors

400unknown_event
An event in events doesn’t exist.
400no_events
events is empty.
400unknown_mailbox
A mailbox in mailboxIds isn’t one the key’s person can see.
400url_*
The address isn’t allowed. The code says why.
403content_needs_messages_read
includeContent without messages:read.
403contacts_need_contacts_read
contact.* events on a key without contacts:read.
409limit_webhooks
The organisation already has 10.
409cannot_resume
It was turned off for good.
429rate_limited
Test sends and redeliveries: 10 a minute per organisation.