maat_partner_…), you swap it at POST /v1/token for a short-lived bearer token that
is scoped to exactly one Maat workspace, and you send that token in the
Authorization header on every call. That is the whole model.
https://maatstays.wtf/v1 — the only environment
this contract is published against today. Which tenancy your requests land in is decided
by your key, never by the hostname.
The key
- Your key looks like
maat_partner_a1b2c3d4e5f60718_…and is shown once, when it is issued. Store it in a secret manager; we hold only a hash and cannot show it again. - Every key is issued for exactly one workspace — a workspace is one tenancy on Maat, the container a portfolio’s properties and calendars live in — and is either a sandbox key or a production key. Nothing you send can change that — see Sandbox.
- The key opens exactly one door: the token exchange. It never authenticates a contract endpoint directly.
- The exchange takes an empty body, on purpose. The workspace, the environment and your identity all come from the key itself; anything you put in the body is ignored.
The token
- Tokens live for fifteen minutes by default and never more than an hour
(
expires_intells you exactly). Mint one per batch of work, not one per request — the exchange has its own, separate rate ceiling. - Store the key, mint tokens from it. Never persist a token, and never send one as
a cookie or in a query string — the API reads the
Authorizationheader and nothing else. - Revocation does not wait for expiry. We re-check the key behind a token on every request, so revoking a key kills its outstanding tokens on their next call.
When it is refused
A refused exchange is one indistinguishable401 whether the key is unknown,
revoked, or the secret is wrong — telling those apart would let anyone probe which
credentials exist. If a key that worked yesterday is refused today, talk to your Maat
contact; the answer is on our side.
The token endpoint is the one place in this API that answers refusals with a plain
{ "message": … } body rather than a problem document. Every other response is
application/problem+json — see Errors.