Skip to content

Create a new API key

POST
/v1/api-keys
curl --request POST \
--url https://api.aetherpush.com/v1/api-keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "name": "github-actions-ci", "scopes": [ "deploy", "read" ], "expires_at": "2026-12-31T23:59:59Z" }'

Creates a new API key with the given name and scopes. The response includes the raw key value in the key field. This is the only time the raw key is returned; store it securely.

The tenant’s max_api_keys quota applies — exceeding it returns 429.

Creating an API key requires a dashboard login session. Any other credential receives 403 with code dashboard_session_required.

An account that passed its two-factor setup deadline with MFA still off is refused here with 403 and code mfa_setup_required.

Media typeapplication/json
object
name
required
string
>= 1 characters <= 100 characters
scopes
required
Array<string>
>= 1 items
Allowed values: deploy apps keys read
expires_at

Expiration date (ISO 8601). Must be in the future. Null means no expiration.

string | null format: date-time

Example

{
"name": "github-actions-ci",
"scopes": [
"deploy",
"read"
],
"expires_at": "2026-12-31T23:59:59Z"
}

API key created. Raw key returned in key field.

Media typeapplication/json

Returned only by POST /v1/api-keys. The key field contains the raw secret and is shown exactly once — clients must store it securely. Subsequent reads of the key resource omit this field.

object
id
required
string format: uuid
name
required
string
key_prefix
required
string
scopes
required
Array<string>
Allowed values: deploy apps keys read
expires_at
required
string | null format: date-time
revoked_at
required
string | null format: date-time
last_used_at
required
string | null format: date-time
created_at
required
string format: date-time
updated_at
required
string format: date-time
key
required

The raw API key. Returned only on creation. Store securely.

string

Example

{
"id": "5b3f1c8a-4d2e-4a7c-9a1b-8e6f3c2d1b0a",
"name": "github-actions-ci",
"key_prefix": "aether_sk_live_AbC123XyZ",
"key": "aether_sk_live_AbC123XyZ4567abcdEFGHijkl",
"scopes": [
"deploy",
"read"
],
"expires_at": "2026-12-31T23:59:59Z",
"revoked_at": null,
"last_used_at": null,
"created_at": "2025-04-30T10:00:00Z",
"updated_at": "2025-04-30T10:00:00Z"
}

Missing/invalid name, scopes, or expires_at.

Media typeapplication/json
Error

Standard error envelope. code is the stable machine identifier for client branching and i18n. The wording of error is a human-readable fallback and is not part of the contract. Specialized responses keep narrower code enums where clients already branch on them.

object
error
required

Human-readable error message.

string
code
required

Stable machine code. Prefer this over matching on error. The values this API can answer with are listed in the ApiErrorCode schema of the raw document at https://api.aetherpush.com/openapi.yaml. The field stays an open string here so that a release adding a value does not invalidate this response.

string
requestId

Unique identifier for the request, also exposed as the X-Request-Id response header.

string

Example

{
"error": "The requested resource was not found.",
"code": "not_found",
"requestId": "req_abc123"
}

Unauthenticated.

Media typeapplication/json
Error

Standard error envelope. code is the stable machine identifier for client branching and i18n. The wording of error is a human-readable fallback and is not part of the contract. Specialized responses keep narrower code enums where clients already branch on them.

object
error
required

Human-readable error message.

string
code
required

Stable machine code. Prefer this over matching on error. The values this API can answer with are listed in the ApiErrorCode schema of the raw document at https://api.aetherpush.com/openapi.yaml. The field stays an open string here so that a release adding a value does not invalidate this response.

string
requestId

Unique identifier for the request, also exposed as the X-Request-Id response header.

string

Example

{
"error": "The requested resource was not found.",
"code": "not_found",
"requestId": "req_abc123"
}

Refused. dashboard_session_required for any credential that is not a current dashboard login session, including an API key, named access key, CLI session or session without a recorded origin; mfa_setup_required when the account passed its two-factor setup deadline with MFA still off.

Media typeapplication/json
Any of:
Error

Standard error envelope. code is the stable machine identifier for client branching and i18n. The wording of error is a human-readable fallback and is not part of the contract. Specialized responses keep narrower code enums where clients already branch on them.

object
error
required

Human-readable error message.

string
code
required

Stable machine code. Prefer this over matching on error. The values this API can answer with are listed in the ApiErrorCode schema of the raw document at https://api.aetherpush.com/openapi.yaml. The field stays an open string here so that a release adding a value does not invalidate this response.

string
requestId

Unique identifier for the request, also exposed as the X-Request-Id response header.

string

Example

{
"error": "The requested resource was not found.",
"code": "not_found",
"requestId": "req_abc123"
}

Two causes share this status. The tenant limiter answers RateLimitErrorResponse (error, retryAfterSeconds) with Retry-After. The tenant API key quota answers the Error envelope and no Retry-After.

Media typeapplication/json
One of:
RateLimitError

Returned with HTTP 429 when an endpoint-specific rate limit is hit, including the per-tenant management API budget. Not the process-wide address limiter (see GlobalAddressRateLimitErrorResponse). retryAfterSeconds indicates how long the client should wait before retrying, and matches the Retry-After header when that header is set. code names the limit that fired so clients can translate without matching on error.

object
error
required
string
code
required
string
retryAfterSeconds
required
integer
>= 1
requestId
string

Examples

Tenant management budget spent

{
"error": "Rate limit exceeded",
"code": "tenant_rate_limit_exceeded",
"retryAfterSeconds": 60
}
Retry-After
integer
>= 1

Present only for the tenant limiter.