---
title: "Create an API key"
method: POST
path: "/api-keys"
tags: ["ApiKeys"]
---

# Create an API key

`POST /api-keys`

## Request

- Base URL: `https://api.groundmail.dev`
- URL: `https://api.groundmail.dev/api-keys`
- Auth: HTTP bearer

## Request body

- CreateApiKeyRequest
  - `name` string
  - `scopes` ApiScope[]: What the key may do, e.g. `["emails:send"]` (send only) or `["emails:read", "domains:read", "account:read"]` (read only). Takes precedence over `scope`.
  - `allowed_domains` string[]: Verified domains the key may send from. Needs `emails:send` and cannot be combined with `full`. Sends from other domains get 403 `domain_not_allowed`.
  - `scope` 'full' | 'sending': Legacy. `sending` means `emails:send` + `emails:read`.
  - `test` boolean: Create a test key (`gm_test_…`). It has the same scopes and checks as a live key, but its sends are never delivered: they get simulated events and webhooks and do not count toward plan limits, the sending ramp, stats or billing.
  - `tenant` string: Limit the key to one tenant (its `external_id` or `id`). The key sends only as that tenant (naming another gets 403 `forbidden`), sees and manages only that tenant's emails, domains and suppressions, and can read its own tenant (`GET /tenants/{id}`, `/stats`, `/domains`). Every other endpoint (webhooks, templates, received email, deliverability, events, API keys, other tenants, account settings) answers 403 `forbidden`. With a tenant, `allowed_domains` may be combined with `full`. Deleting the tenant revokes its keys.

## Response `200`

API key created (token shown once)

- CreateApiKeyResponse
  - `id` string, required
  - `name` string, required
  - `scope` 'full' | 'sending', required
  - `scopes` ApiScope[], required
  - `allowed_domains` string[], required
  - `test` boolean: A test key (`gm_test_…`).
  - `tenant` string: The tenant this key is limited to (`external_id`). Present only on tenant keys.
  - `prefix` string, required
  - `token` string, required: Full API key (`gm_…`, or `gm_test_…` for a test key), shown once at creation
  - `created_at` string, date-time, required

## Other responses

- `400`: Invalid field
- `401`: Missing or invalid API key
- `403`: `tenant` set on an account without tenants (`tenants_not_enabled`)
- `404`: The `tenant` does not exist

---

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