API keys

List API keys

Lists the API keys in the current workspace.

GET/keys

Lists the API keys in the current workspace. Secrets and secret hashes are never returned by this or any read endpoint - only prefix, the non-secret leading 12 characters, which is what you match against when you need to identify a key you already hold.

Revoked keys are soft-deleted and are excluded from this list permanently.

Ordering defaults to name, A to Z. order=asc and order=desc switch to createdAt, oldest or newest first; any other value, including a typo, silently falls back to name order.

search matches name and prefix only. Pagination is applied after the workspace's keys are loaded, so totalCount always reflects the full filtered set.

Unlike the webhook endpoints, the key endpoints are not refused for project-restricted keys: a key fenced to specific projects can still read the workspace's key list. It just cannot mint or edit a key outside its own project fence.

Requires the keys:read scope.

curl --request GET \
  --url 'https://api.envless.cloud/keys' \
  --header 'Authorization: Bearer ev_sk_xxxxxxxxxxxx'
Try itGEThttps://api.envless.cloud/keys
Query parameters

Authorization

  • Authorizationstringrequiredheader

    Bearer token: an Envless API key (ev_sk_…), created in the dashboard or with POST /keys. The key is bound to one workspace; every request runs inside it.

Query parameters

  • limitintegermin 1max 100

    Page size. Must be a whole number between 1 and 100.

    Default: 25

  • offsetintegermin 0

    Number of keys to skip. Must be a whole number of 0 or greater.

    Default: 0

  • searchstring

    Case-insensitive substring match against the key name and prefix. Never matches the secret.

  • orderenum<string>

    asc and desc sort oldest and newest first by createdAt. Anything else, including omitting it, sorts by name A to Z.

    Options: "name", "asc", "desc"

Responses

200OK

List API keys succeeded.

  • successbooleanrequired
  • codeintegerrequired

    The HTTP status of this response, repeated in the body.

  • messagestringrequired
  • errornullrequired
  • dataobjectrequired
    Show child attributesHide child attributes
    • keysobject[]required
      Show child attributesHide child attributes
      • idstringrequired
      • namestringrequired
      • prefixstring | null

        The non-secret leading segment, for identifying a key in a list.

      • scopesobjectrequired

        Per-resource access level for an API key.

        Keys: workspace, products, product-access, projects, environments, variables, versions, members, roles, keys, webhooks · values enum<string>

        Options: "none", "read", "write"

      • projectIdsstring[]required

        Projects this key is fenced to. An empty array means unrestricted.

      • activebooleanrequired
      • lastUsedAtstring | nulldate-time
      • keyRollsinteger
      • createdAtstringrequireddate-time
      • lastRolledAtstring | nulldate-time
    • paginationobjectrequired
      Show child attributesHide child attributes
      • limitintegerrequired
      • offsetintegerrequired
      • totalCountintegerrequired
      • hasMorebooleanrequired
  • _reqobject
    Show child attributesHide child attributes
    • reqIdstring
    • resTimeinteger | null
{
    "success": true,
    "code": 200,
    "message": "OK",
    "error": null,
    "data": {
        "keys": [
            {
                "id": "<string>",
                "name": "<string>",
                "prefix": "<string>",
                "scopes": {
                    "workspace": "none",
                    "products": "none"
                },
                "projectIds": [
                    "<string>"
                ],
                "active": true,
                "lastUsedAt": "2026-05-30T10:14:22.000Z",
                "keyRolls": 1,
                "createdAt": "2026-05-30T10:14:22.000Z",
                "lastRolledAt": "2026-05-30T10:14:22.000Z"
            }
        ],
        "pagination": {
            "limit": 1,
            "offset": 1,
            "totalCount": 1,
            "hasMore": true
        }
    },
    "_req": {
        "reqId": "<string>",
        "resTime": 1
    }
}

Error envelope

Every failure below returns the same shape with success: false; branch on error.code, never on message.

  • successbooleanrequired
  • codeintegerrequired

    The HTTP status of this response, repeated in the body.

  • messagestringrequired
  • errorobjectrequired

    Machine-readable failure detail. Null on success.

    Show child attributesHide child attributes
    • codeenum<string>required

      Stable error code. Branch on this, never on message.

      Options: "auth.api_key_required", "auth.api_key_not_found", "auth.api_key_user_missing", "auth.api_key_owner_not_member", "auth.scope_missing", "auth.scope_ceiling_exceeded", "auth.key_project_restricted", "auth.product_restricted", "auth.permission_denied", "auth.self_mutation_forbidden", "auth.step_up_required", "auth.step_up_fresh_required", "auth.cli_token_not_accepted", "auth.two_factor_required", "auth.workspace_two_factor_required", "auth.two_factor_invalid", "auth.two_factor_replayed", "auth.two_factor_locked", "auth.two_factor_not_enabled", "auth.two_factor_already_enabled", "request.body_must_be_json", "request.body_invalid", "request.body_too_large", "request.rate_limited", "request.invalid_pagination", "workspace.not_found", "workspace.slug_conflict", "workspace.limit_reached", "workspace.delete_last", "workspace.delete_too_early", "workspace.delete_has_projects", "domain.not_configured", "domain.not_found", "domain.invalid", "domain.taken", "domain.attempt_limit", "product.not_found", "product.slug_conflict", "product.locked", "project.not_found", "project.ambiguous_product", "project.slug_conflict", "environment.not_found", "environment.slug_conflict", "environment.expose_disabled", "environment.expose_private_product", "variable.not_found", "variable.name_conflict", "variable.ciphertext_invalid", "variable.baseline_drifted", "version.not_found", "member.not_found", "member.already_exists", "member.self_invite", "member.self_mutation", "member.owner_immutable", "member.owner_cannot_leave", "member.seat_limit", "invite.already_pending", "role.owner_not_assignable", "role.limit_reached", "role.immutable", "role.in_use", "invite.not_found", "invite.expired", "role.not_found", "role.name_conflict", "key.not_found", "key.limit_reached", "webhook.not_found", "webhook.delivery_not_found", "plan.limit_reached", "plan.upgrade_required", "request.not_found", "request.method_not_allowed", "request.conflict", "auth.unauthorized", "auth.forbidden", "request.invalid", "server.error"

    • resourcestring

      The resource or scope the failure relates to.

    • fieldstring

      The request field that caused the failure.

  • dataobject | nullrequired

    Null on most failures. A plan limit carries { limit, current }.

  • _reqobject
    Show child attributesHide child attributes
    • reqIdstring
    • resTimeinteger | null
{
    "success": false,
    "code": 400,
    "message": "Something went wrong.",
    "error": {
        "code": "auth.api_key_required",
        "resource": "<string>",
        "field": "<string>"
    },
    "data": {},
    "_req": {
        "reqId": "<string>",
        "resTime": 1
    }
}

400Bad Request

request.invalid_pagination - limit or offset is not a whole number, or limit is outside 1-100.

401Unauthorized

  • auth.api_key_required - the Authorization header is missing, or its value does not start with ev_sk_.
  • auth.api_key_not_found - the key is unknown, inactive or revoked.
  • auth.api_key_user_missing - the key is valid but its owner no longer exists.
  • auth.api_key_owner_not_member - the key's owner is no longer a member of the key's workspace.

403Forbidden

  • auth.workspace_two_factor_required - the workspace requires two-factor authentication and the key's owner has not turned it on.
  • auth.scope_missing - the key lacks a scope this operation requires; error.resource names it.

500Internal Server Error

server.error - an unexpected error; retry with backoff.

503Service Unavailable

server.error - the API is in maintenance mode or is missing its configuration; retry with backoff.