List API keys

GET/api/v1/api-keys
Requires anorganization API keywith the scopeaccount:read

The keys your organization holds, with their prefixes, scopes and last use.

Listing is available to a key; creating and revoking are not. A leaked key that could mint its own replacement would outlive the revocation of the key that leaked, so those stay in the dashboard on purpose.

Request

GET/api/v1/api-keys
curl -X GET 'https://app.mailyte.com/api/v1/api-keys' \
  -H 'Authorization: Bearer mk_live_YOUR_API_KEY'
The key names its own organization, so no X-Organization-ID header is needed.

Response

Success.

  • dataarray<object>
    • objectstringapi_key
    • idstring

      Unique identifier for the key.

    • namestring

      Your label for it. Never null: `api_keys.name` is NOT NULL and `POST /api-keys` requires it, so every response that carries a key carries a name.

    • prefixstring

      `mk_live_` followed by 8 characters. This is the public lookup identifier, **not secret material**: the 32 secret characters follow it and are stored only as a hash. It is what lets you tell two of your own keys apart in an audit log, and it is safe to log. Never null: the column is NOT NULL and unique, because authentication looks the row up by it. A prefix beginning `mk_dead_` instead is a pre-2026-09-17 key that never authenticated anything and has been revoked -- see `revoked_reason`.

    • scopesarray

      The permissions this key grants, as the flat `resource:action` strings the authoriser checks. **An empty list grants nothing** -- it is not a wildcard. Scopes cannot be changed after a key is minted; create a new key.

    • modestringlive | test

      A `test` key validates a send exactly as a live one would — verified sender, suppression check, rate limit — and then delivers nothing and records nothing. Use one in CI. Test mode is a property of the key rather than a request parameter, so it cannot be switched on by a stray flag in production code, and a live key has no way to express it.

    • statestringactive | expired | revoked

      The one lifecycle answer, and **expiry beats the stored status**: authentication refuses an expired key whatever its status column says, so a key reported `active` past its expiry would be a key every request is rejecting. Only `active` authenticates.

    • revoked_reasonstring

      Why we revoked it, when we did rather than you. **null means NONE was recorded** -- either the key is not revoked at all, or you revoked it yourself, which the API does not annotate. It is never "we could not read the reason", so null must not be shown as a revoked key with an unexplained cause: read `state` to learn whether it is revoked and this only to learn why WE did it. A key that silently stops working reads as a breach; one that says `legacy_never_functional` reads as what it is.

    • ip_allowlistobject

      Enforced at authentication time. `enabled: false` with a populated list is a configured allowlist that is currently off, not a contradiction.

      • enabledboolean
      • addressesarray<string>

        IPv4/IPv6 addresses or CIDR ranges.

    • last_usedobject

      Grouped because both halves carry the same caveat: **the timestamp is throttled to at most one write a minute**, so a key used two seconds ago can report a time up to a minute behind. That is deliberate -- a key serving a thousand requests a minute costs one row update rather than a thousand. Good enough for "is this key still in use"; it is not a request log, which is what the events endpoints are for.

      • atstring

        ISO 8601 UTC. **null means the key has never been used**, since it was minted -- NONE, not "not used recently" and never "we could not tell". Usage is written by the authenticating middleware on every accepted request, so a null here is a positive statement that no request has ever authenticated with this key. May be up to a minute stale, as above, which is the one thing it will not tell you precisely.

      • ipstring

        The address of the request that last actually recorded usage -- because of the throttle, not necessarily the most recent request. **null alongside a null `at` means the key has never been used** (NONE). null alongside a non-null `at` is the other kind of null: the key WAS used and the address could not be determined for that request, so read it as unknown and not as "used from nowhere". This is how you spot a leaked key being used from somewhere you do not recognise.

    • expires_atstring

      ISO 8601 UTC. **null means the key does not expire** -- NONE, there is no expiry set, and it is optional at creation. **Do not treat null as "expired" or as "unknown"**: a client that sorts or filters on this and reads a null as a past date will hide or disable a key that works perfectly. Expiry is the one thing that overrides the stored status, so `state` already accounts for it -- read `state` to decide whether a key authenticates, and this only to show or renew the date.

    • created_atstring

      ISO 8601 UTC.

Returned inside the standard envelope.

Errors

StatusWhen
401The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist.
403The key is valid but may not do this: it lacks the required scope, its IP allowlist does not include you, or this endpoint does not accept API keys.
404No such resource in this organization.
422The request was understood but the values were not acceptable.
429Too many requests, or the organization has spent its sending allowance. `Retry-After` says how long to wait.

Every status, with what causes it and what to do, is on the error reference.