There are two ways to authenticate, and they reach different parts of the API.
Create one in the console under Settings → API keys. Give it a name and pick its scopes; the token is shown once, at creation, and stored only as a hash — Coldfeet cannot show it to you again, so put it in your secret store before closing the dialog.
A token looks like cf_ followed by 64 hexadecimal characters. Send it as a bearer token:
Authorization: Bearer cf_1a2b3c…
The scheme is case-sensitive: Bearer, not bearer.
Tokens do not expire. Rotation is deliberate — create the replacement, deploy it, then delete the old one. Deleting takes effect immediately.
Scopes are named resource:action — domains:read, quarantine:write, messages:read
and so on. The full list, with what each one allows, is on the Settings → API keys page as you
pick them, and every endpoint in the reference names the scope it requires. Neither is
restated here, because a list in a guide is a list that goes stale.
Two of them are worth calling out:
messages:read is metadata — the trace, verdicts, delivery attempts. Downloading the message
itself needs mail:read, which is a separate decision because it is a separate kind of access.quarantine:write, policy:write, members:write and settings:write change what
happens to mail, or who can reach this organization. Grant them to automation you would trust
with the console.Ask for the narrowest set that does the job. A token calling an endpoint whose scope it lacks gets
403 naming the missing scope, which is a clearer failure than a partial result.
read or writeThose were the scope names before this split, and they still work. They mean exactly what they
meant when they were issued: read covers domains, trace metadata and scheduled reports, and
write covers managing domains and scheduled reports. They do not pick up anything that has
opened to tokens since — a write token cannot release quarantined mail or add a member, and
never will. Reissue with named scopes when you want more.
A token belongs to the organization that created it. If you are a partner with customers beneath
you, add tenants:children and the token's other scopes also apply inside those customers —
one credential to rotate instead of one per customer.
It grants nothing by itself: a token scoped tenants:children and quarantine:read can read
customers' quarantines and do nothing else, in them or anywhere. It reaches one level down, to
organizations that name yours as their parent, and never sideways or upwards. Enumerate them with
GET /tenants/{yourId}/children, then call the ordinary endpoints with the customer's id in the
path.
Most of what the console can do, it does with a session token from signing in. Some endpoints take only a session and are marked Session only in the reference: personal settings, anything that answers a question about your own account, and the token endpoints themselves — a token that could mint tokens could widen its own scopes.
Composing and sending mail is session-only for a different reason, which is that a leaked credential should not be able to send as you, and so is configuring journal endpoints.
If you need automation against one of those, say so — which endpoints matter decides what opens up next.
Two checks run on every request. The token has to be valid, and the organization in the path has to
be the one the token was issued for, or one of its customers if the token has tenants:children.
A suspended organization is refused as well, with a message saying so rather than an empty result;
so is a customer whose partner is suspended.
Last updated