notifications
PUT /v1/outbound-mail
Attach or replace this organisation's own mail service.
Authentication
Send an API key as a bearer token. This endpoint does not state a specific permission in the specification, so give your key the least it needs and check the response rather than assuming.
Where your organisation id goes
This endpoint takes org_id as a query parameter. Leave it out and the call covers your whole tenancy subtree; send it to narrow the call to one organisation.
Your organisation id is on the API keys screen in your dashboard, beside the key itself. It is the same id in every call you make.
Try it
Replace anything in angle brackets with your own values, and the key placeholder with a key from your dashboard.
curl -X PUT https://api.zinndigital.com/v1/outbound-mail \
-H "Authorization: Bearer zdk_live_…" \
-H "Content-Type: application/json" \
-d '{ "provider": <string<smtp, mailgun, sendgrid, postmark, ses, resend>>, "from_domain": <string>, "credential": <string> }'Signed in? The API console in your dashboard fills in your real organisation id and your own key, and runs the request against the live API so you can see the actual response. Open this endpoint in the API console
Details
PUT rather than POST because a From header is singular: an organisation has exactly one sending service, and the commonest reason to be on this screen is switching provider. The credential is write-only. It goes straight to the secret vault and the row keeps only a pointer; it is never returned by any endpoint in any state. Attaching does NOT switch the sender. A new or replaced credential resets the account to `unverified`, and only a completed round trip - a real test message, and the code out of it - makes it the From address. A provider that accepts a message and then bounces it is indistinguishable from a working one at the moment of the call, so acceptance is not proof.
Parameters
| Name | Type | Required | What it is |
|---|---|---|---|
org_id (query) | string | No | The organization to act on. Omitted (or empty) means your own. |
Request body
| Name | Type | Required | What it is |
|---|---|---|---|
provider | string<smtp, mailgun, sendgrid, postmark, ses, resend> | Yes | `ses` is Amazon SES over its documented SMTP interface, so the credential is an SES SMTP username and password rather than an AWS access key. |
from_domain | string | Yes | The domain your From address will use - a domain, not an address. The local part still comes from the message type, so a receipt leaves as `billing@` and a password reset as `no… |
credential | string | Yes | The API key, server token or SMTP password. Never returned. |
config | object | No | The non-secret settings this provider needs - SMTP host/port/username, Mailgun domain and region, the SES region, the Postmark message stream. The exact fields are returned per… |
Response
| Name | Type | Required | What it is |
|---|---|---|---|
can_configure | boolean | Yes | Whether this organisation's plan includes its own sending identity - the agency and reseller plans do, a plain client plan does not. A claim about the PLAN, never the authorisat… |
account | OutboundMailAccount | Yes | null when this organisation sends on the platform's account. |
providers | object[] | Yes | The provider catalogue AND the fields each one needs, served from the same definition the API validates against - so the form a customer fills in and the rules it must satisfy c… |
sending_as | string<own, platform> | Yes | Who is actually paying for this organisation's mail right now. `platform` whenever no account is attached OR the attached one has not completed its round trip. |
fallback_notice | string | Yes | Plain-language explanation shown when `sending_as` is `platform`; empty otherwise. Part of the contract rather than presentation - an empty state that does not say who is paying… |
client_orgs_held | integer | Yes | How many client organisations under this one currently have their non-essential notifications held because no own mail provider is connected (owner ruling 2026-09-03). `0` when… |