API reference › API keys › Create key
Create an API key
/v1/api-keyspropgate keys createMints a key for the tenant the presenting key belongs to, without repeating
the signup flow. Any of a tenant's own keys can authenticate this call,
including a key created from confirm.
| Field | Type | Description |
|---|---|---|
| name* | string | A label for this key, up to 64 characters. Shown back in `GET /v1/api-keys` to tell keys apart — e.g. `staging`, `ci`. |
curl -s -X POST https://api.propgate.dev/v1/api-keys \
-H "authorization: Bearer pg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "content-type: application/json" \
-d '{"name":"staging"}'{
"data": {
"key": "pg_live_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"createdAt": "2026-08-05T14:02:11.000Z",
"createdBy": "you@example.com",
"id": "019fcf6b-...",
"lastUsedAt": null,
"name": "staging",
"object": "api_key",
"prefix": "pg_live_9f2a",
"revoked": false,
"revokedAt": null
},
"error": null,
"meta": null
}key is returned exactly once, here, and never again on any endpoint.
Only its hash is stored, so there is no code path that could show it a second
time even by accident — that is what makes "we cannot show you that key
again" a property of the storage rather than a policy someone could quietly
change.
createdBy propagates from whichever key authenticated this request: an
operator-minted key has no creator, and null propagates as null rather than
being filled in with a guess.
Failure modes
{
"data": null,
"error": {
"message": "name: Invalid input: expected string, received undefined"
},
"meta": null
}A tenant may hold at most fifty active keys — a tripwire against an
unattended loop turning this endpoint into unbounded row growth, not a quota
any real integration is expected to approach. Revoked keys don't count
toward it. The 422 names both halves of the problem: the limit, and how
many you currently hold, so an agent reading it knows exactly what to do
next.
{
"data": null,
"error": {
"message": "active key limit of 50 reached, and you hold 50; revoke one before creating another"
},
"meta": null
}