Mail Kontier sends on your behalf: the message log with delivery events, resend, the suppression list, blocked-mail retry, and recipients' marketing consent. Templates, mail kinds and sending providers are configured in the dashboard.
Count the mail that could not be sent
How much mail is held because something is misconfigured, broken down by cause, plus the age of the oldest. Mail we deliberately did not send (a suppressed address, a marketing opt-out) is never counted here — it is not a problem to fix. Requires the mail.read permission.
Required scope: mail.read (Read mail history).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Count the mail that could not be sent › Responses
OK
Send the held mail again
Rebuilds each held message from its source document and queues it again, in bounded batches. It never rewrites the original record: each retry produces a new message and the held one stays as history. Only mail held for a configuration problem is retried — mail held for a missing address is reported separately, because a retry cannot fix it. Requires the mail.write permission.
Required scope: mail.write (Manage mail suppressions).
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Send the held mail again › Request Body
Send the held mail again › Responses
OK
List marketing consent
Keyset-paginated list of the org's current marketing-consent states, filterable by state, purpose, and email substring. Requires mail.read.
Required scope: mail.read (Read mail history).
query Parameters
limitPage size (default 50, max 200).
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
stateFilter by state: opted_in|soft_opt_in|opted_out|unknown.
purposeFilter by consent purpose; defaults to all.
emailCase-insensitive substring match on the recipient address.
sortOrdering: updated_at, email, state, basis or source, each with an optional :asc/:desc suffix (default updated_at:desc). An unknown value is rejected. email orders by lower(email), the key consent is unique on. source is nullable: rows without one are grouped together and sort last ascending, first descending. Cursors are bound to the ordering that issued them, so changing sort mid-walk needs a fresh first page.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List marketing consent › Responses
OK
Record a recipient's consent
Records ONE recipient's marketing-consent state with proof rules — never a bulk opt-in. Recording opted_in REQUIRES proof_text: without it the call is refused with 422 CONSENT_PROOF_REQUIRED rather than quietly recorded as unknown (send state=unknown for that). soft_opt_in cannot be set by hand. The change is appended to the demonstrability record. Requires mail.consent.manage.
Required scope: mail.consent.manage (Manage marketing consent).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Record a recipient's consent › Request Body
emailThe recipient address (required).
stateThe state to record: opted_in | opted_out | unknown. soft_opt_in is not manually settable (it is seeded from sales).
customer_idThe customer this address belongs to, when known.
proof_textThe consent statement the recipient agreed to. Required to record opted_in; without proof an opt-in lands as unknown (§4.1).
purposeConsent purpose; defaults to marketing_email.
Record a recipient's consent › Responses
OK
List marketing-consent transitions
The append-only log of marketing-consent changes: what each state moved from and to, who moved it, and the evidence that change carried (the statement agreed to, the IP, the user agent). This is the record GDPR Art 7(1) demonstrability is served from — the current state alone cannot show what changed when. Filter by email to get one recipient's trail. Keyset-paginated, newest first. Requires mail.read.
Required scope: mail.read (Read mail history).
query Parameters
limitPage size (default 50, max 200).
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
emailFilter to one exact recipient address (case-insensitive). This is the usual call: the history is opened from a single permission row.
purposeFilter by consent purpose; defaults to all.
customer_idFilter to one customer's transitions.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List marketing-consent transitions › Responses
OK
List sent-mail history
Keyset-paginated list of the calling organization's sent-mail history (branded dispatch audit). Requires the mail.read permission.
Required scope: mail.read (Read mail history).
query Parameters
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
source_kindDrill-down filter on the originating document kind, e.g. "invoices" (case-sensitive).
source_idDrill-down filter on the originating entity id (UUID).
template_keyFilter to one email: the template_key its producer stamps (MailKindResponse.template_key), e.g. "invoice_issued".
statusFilter by status. "suppressed" is a correct decision not to send; "blocked" is a send that failed and an operator can fix — block_reason on each row says which.
recipient_kindFilter to messages that actually went to this class of mailbox: customer|team|customer_broadcast. Stamped from the resolved recipient, so a customer-audience email a tenant routed to their own finance address reads "team". Omit to include unclassified rows, which predate the classification and match no value.
recipientFilter to messages addressed to this email in any of to/cc/bcc (case-insensitive).
customer_idFilter to messages addressed to any of the customer's on-file addresses — the account email plus every role-addressed contact — in any of to/cc/bcc (case-insensitive).
sortOrdering: created_at, status, recipient_kind or source_kind, each with an optional :asc/:desc suffix (default created_at:desc). An unknown value is rejected. Unclassified rows (recipient_kind or source_kind NULL) group together at the end under :asc and at the start under :desc. Cursors are bound to the ordering that issued them, so changing sort mid-walk needs a fresh first page.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List sent-mail history › Responses
OK
Get one sent mail message
Returns a single mail message by id (organization-scoped), including its delivery status and audit fields. Requires the mail.read permission.
Required scope: mail.read (Read mail history).
path Parameters
idMail message id (UUID).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get one sent mail message › Responses
OK
Get one message's delivery history
Keyset-paginated delivery history for one of the calling organization's messages — what the sending account reported back about it, newest first. A message that was never handed to a sending account has an empty history. Requires the mail.read permission.
Required scope: mail.read (Read mail history).
path Parameters
idMail message id (UUID).
query Parameters
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get one message's delivery history › Responses
OK
Send this email again
Rebuilds the email from the document it was generated from and sends it to the same recipients, as a NEW entry in the history — the original is never altered. Returns 409 when email delivery is switched off, and 422 when the email cannot be rebuilt (a one-off send) or was part of a campaign, which must be re-sent from the campaign so every recipient is checked individually. Requires the mail.write permission.
Required scope: mail.write (Manage mail suppressions).
path Parameters
idThe mail message id to send again (UUID).
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Send this email again › Request Body
idempotency_keyToken that makes this safe to retry: the same token collapses onto one send, a new token sends again. Omit for a stable per-user, per-day default.
Send this email again › Responses
OK
Get what a sandbox withheld
Returns the subject, recipients and rendered bodies of a message a sandbox workspace did not send because a recipient is outside the organization (block reason sandbox_recipient). 404 for a message that was not withheld from a sandbox. Requires the mail.read permission.
Required scope: mail.read (Read mail history).
path Parameters
idMail message id (UUID).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get what a sandbox withheld › Responses
OK
View an email as sent
Returns the archived copy of a sent business letter (a payment reminder, a quote email, a receipt): the headers including Message-Id, the subject, both bodies and the attachments with their SHA-256, exactly as handed to the sending account. Each read is recorded in the audit log. 404 for a message with no archived copy: not a letter, not sent, or sent before archiving began. Requires the mail.read permission.
Required scope: mail.read (Read mail history).
path Parameters
idMail message id (UUID).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
View an email as sent › Responses
OK
List mail suppressions
Keyset-paginated list of the calling organization's do-not-send suppression entries (hard bounces, complaints, and manual adds). Requires the mail.read permission.
Required scope: mail.read (Read mail history).
query Parameters
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
sortOrdering: email, reason or created_at, each with an optional :asc/:desc suffix (default created_at:desc). email orders case-insensitively, on lower(email). reason orders by the STORED value (hard_bounce|complaint|unsubscribe|manual), not by its translated label. An unknown value is rejected. Cursors are bound to the ordering that issued them, so changing sort mid-walk needs a fresh first page.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List mail suppressions › Responses
OK
Add a mail suppression
Manually suppress a recipient address (reason "manual"). Idempotent: re-adding an already-suppressed address is a no-op. Requires the mail.write permission.
Required scope: mail.write (Manage mail suppressions).
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Add a mail suppression › Request Body
emailThe recipient address to suppress. Added with reason "manual".
Add a mail suppression › Responses
Created
Remove a mail suppression
Lift the suppression for an address (the operator re-consent action), named by the ?email= query parameter. Idempotent: removing an address that is not suppressed succeeds. Requires the mail.write permission.
Required scope: mail.write (Manage mail suppressions).
query Parameters
emailThe suppressed recipient address to lift (case-insensitive).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Remove a mail suppression › Responses
No Content