API keys are issued by a company admin in the Yeti office UI, not through this
API. An API has no business issuing its own credentials, which is why there is no
api-keys scope and no endpoint here that creates one.
The key is shown once, at creation. We store only a SHA-256 hash of it, so a lost key cannot be recovered — it can only be replaced. Put it somewhere your deployment can read it and nowhere else; it is not a value to paste into a ticket or a chat message.
Send the key as a bearer token on every request. There is no session and no login call — a key that worked a moment ago still has to be sent on the next request.
curl https://api.winteriscoming.fyi/v1/me \
-H "Authorization: Bearer yeti_pk_..."
GET /v1/me is the first call worth making. It confirms the credential works,
which company it is bound to, and which scopes it holds:
{
"data": {
"api_key": {
"id": "12",
"name": "Zapier",
"identifier": "yeti_pk_a1b2c3…9f4e",
"scopes": ["sites:read", "services:read"],
"expires_at": null,
"revokes_at": null
},
"company": { "id": "42", "name": "Cascade Snow Co", "currency": "CAD" }
}
}
Without this call, a missing scope only ever shows up as a 403 on some unrelated
endpoint, and working out which grant is absent turns into a support ticket.
Note what is not returned: the key itself. identifier is the prefix and the
last four characters, which is enough to tell two keys apart in a log line without
the secret existing anywhere but your configuration.
revokes_at is a warning, not an errorIf it is set, this key is in a rotation grace period: a replacement has been
issued and this one stops working at that timestamp. Deploy the new key before
then. Seeing this field is how you avoid ever seeing api_key_revoked.
Every response is already limited to the company the key belongs to. There is no
company id in any URL — the legacy API put one in the path, where a client could
edit it. If a key is granted more than one company, select between them with the
X-Yeti-Company header; single-company keys ignore it.