API keys serve as a way to authenticate applications where individual user identification and authentication are not required. They function as permanent access tokens.

Create an API Key for a Project

You can create a project-specific API key using the GraphQL API:

mutation {
  createApiKey(
    projectSlug: "my-blog",
    description: "User-friendly description of the key",
    memberships: [{role: "editor", variables: [{name: "language", values: ["cs"]}]}]
  ) {
    ok
    error {
      code
    }
    result {
      apiKey {
        id
        token
        identity {
          id
        }
      }
    }
  }
}

This returns three identifiers:

  • API Key ID: Used for disabling this API key later.
  • Identity ID: Used to modify the API key's memberships and permissions.
  • Token: A bearer token used for authenticating your GraphQL requests.

Create Global API Key

mutation {
  createGlobalApiKey(
    description: "Global API key description",
    roles: ["super_admin", "monitor"]
  ) {
    ok
    error {
      code
    }
    result {
      apiKey {
        id
        token
        identity {
          id
        }
      }
    }
  }
}

This also returns three identifiers similar to creating a project-specific API key.

Custom Token Generation

Both createApiKey and createGlobalApiKey support the optional tokenHash parameter. If you provide a SHA-256 hash of the token you wish to use, the API will not generate a new token, and the token field in the response will be empty. This allows you more control over token management but requires you to securely generate and store the original token yourself.

Trusted-proxy API keys

Available since 2.2

Both createApiKey and createGlobalApiKey accept options.trustForwardedClientInfo: true. An api_key with that flag honors the X-Contember-Client-IP and X-Contember-Client-User-Agent headers from the request, so session tracking, audit logs and Content API userInfo see the real end-user IP/UA rather than the proxy's socket.

This is intended for backend services that proxy user requests. The flag carries a strict security contract on the proxy side — see proxy trust before enabling.

mutation {
  createGlobalApiKey(
    description: "Backend → Contember (per-user)",
    roles: ["login"],
    options: { trustForwardedClientInfo: true }
  ) {
    ok
    result { apiKey { id token } }
  }
}

The flag cannot be flipped on an existing api_key. To remove it, disable the key and create a new one.

Audit

(since 2.2) Every createApiKey / createGlobalApiKey is recorded as api_key_create in the audit log with the api_key id, identity, and memberships/roles — never the token or its hash. disableApiKey is recorded as api_key_disable.

Listing API keys

Available since 2.2

Permanent keys can be listed so a management UI can show which keys exist, who they belong to, and when they were last used. Two entry points cover the project-scoped and global cases — both return the enriched ApiKey type and never expose the token.

Project-scoped permanent keys (excludes session tokens and global keys) live on the Project type and require the project.view members permission:

query {
  projectBySlug(slug: "my-blog") {
    apiKeys {
      id
      description
      type
      enabled
      createdAt
      lastUsedAt
      expiresAt
      identity {
        id
        # memberships, handy for cloning a key when re-issuing it
        projects {
          project { slug }
          memberships { role variables { name values } }
        }
      }
    }
  }
}

Global permanent keys (those created via createGlobalApiKey — their identity carries global roles and no project membership) are read through the top-level query, gated by the apiKey:list permission (granted only to SUPER_ADMIN by default):

query {
  globalApiKeys {
    id
    description
    type
    enabled
    createdAt
    lastUsedAt
    expiresAt
    identity { id roles }
  }
}

Both fields return an empty list rather than throwing when the caller may not list the keys, so a batched query doesn't abort on a single forbidden target.

ApiKey fields

FieldNotes
idThe api-key id. Pass to disableApiKey.
identityThe key's identity — identity.id to edit memberships, identity.projects for its project memberships, identity.roles for a global key's roles.
descriptionHuman-readable label, stored on the key's identity (identity.description).
typeApiKeyTypeSESSION, PERMANENT, or ONE_OFF. Listings only return PERMANENT keys.
enabledfalse once the key has been disabled (disableApiKey).
createdAtWhen the key was minted.
lastUsedAtTimestamp of the most recent request authenticated with this key.
expiresAtExpiration, if any (permanent keys typically have none).

Session keys vs permanent keys

API keys come in two flavors:

  • Permanent — created by createApiKey / createGlobalApiKey, no expiry, intended for applications and integrations.
  • Session — minted by signIn / signInIDP / signInPasswordless / createSessionToken, short-lived, tied to a person. Documented in sessions — there you'll also find how to list and revoke active sessions.

Disable API Key

mutation {
  disableApiKey(id: "some-api-key-id") {
    ok
  }
}

Use the API Key ID to disable the API key. Do not confuse this with the Identity ID.

To invalidate every API key (session and permanent) for a target person at once, use forceSignOutPerson.