---
title: "List API keys for a project"
method: GET
path: "/api/projects/{id}/api-keys"
tags: ["API Keys"]
---

# List API keys for a project

`GET /api/projects/{id}/api-keys`

## Request

- Base URL: `https://api.sendly.now`
- URL: `https://api.sendly.now/api/projects/{id}/api-keys`
- Auth: one of:
  - API key in cookie `better-auth.session_token`
  - OAuth 2 (authorization code, authorization URL `https://app.sendly.now/api/auth/oauth2/authorize`, token URL `https://app.sendly.now/api/auth/oauth2/token`, scopes: `api-keys:read`)

Returns every key on the project, revoked ones included — filter on `revokedAt` to show only live keys. Never returns a token or its hash: `lastFour` is the only fragment of the secret that survives creation.

Requires the `api-keys:read` scope — See which API keys exist, including what each one is allowed to do.

## Path parameters

- `id` string, required: Project id.

## Response `200`

API key list

- ApiKeyListResponse: Every API key on the project, including revoked ones — filter on `revokedAt` for live keys.
  - `data` ApiKey[], required
    - `createdAt` string, date-time, required: ISO 8601 datetime string
    - `domainId` string, uuid, nullable, required
    - `id` string, uuid, required
    - `lastFour` string, required: Last 4 characters of the token — the only fragment of the secret that survives creation.
    - `lastUsedAt` string, date-time, nullable, required: ISO 8601 datetime string
    - `legacyGrantPreset` 'FULL' | 'SENDING_ONLY', required: The coarse preset the key was minted under. It picks the token prefix (`sk_` vs `pk_`) and the rate-limit window, and it is the key's authority ONLY while `scopes` is empty — which is true just of keys minted before scopes existed. Read `scopes` to learn what a key can do.
    - `mode` 'LIVE' | 'TEST', required: Where mail sent with this key may go. `LIVE` sends from your verified domains. `TEST` can only send from this project's sandbox address, whose recipient list is your own verified account addresses, so a test key cannot reach a customer whatever it is asked to do. Fixed at creation.
    - `name` string, required
    - `projectId` string, uuid, required
    - `revokedAt` string, date-time, nullable, required: Set once the key is revoked. Revoked keys are NOT filtered out of list/get responses.
    - `scopes` string[], required: The explicit scope grant this key carries. Empty on a key minted before this column existed — that row's grant is derived from `legacyGrantPreset` instead at request time.
  - `success` true, required

## Other responses

- `400`: Validation error
- `401`: Unauthorized — missing or invalid auth
- `403`: Forbidden — insufficient permissions or project disabled
- `404`: Resource not found
- `429`: Rate limit or billing limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/sendly/apis/sendly-api.md) · [All operations](https://skmtc.dev/sendly/apis/sendly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sendly/apis/sendly-api/revisions/ce7cfb7f7c7e?raw)
