Skip to main content
HoneyHive has three families of API key. This page explains what each family is for, how to create, scope, and revoke fine-grained keys, and how to create and revoke ingestion keys. The families differ in how their permissions work:
  • Classic API keys carry a fixed set of permissions for a single scope. What a classic key can do is determined by the kind of key it is, and cannot be changed.
  • Fine-grained API keys carry only the permissions you select when you create the key. Each key is bound to a scope and its descendants, expires on a date you choose, and cannot be edited after creation.
  • Ingestion API keys carry one fixed capability: sending traces and events to a single project. They reach nothing else, never expire, and can be revoked at any time.

Key types

See API Key Permissions for the full set of permissions a project API key carries.

Fine-grained keys

A fine-grained key is defined by three things you choose when you create it:
  • A scope it is bound to. Either an organization or a workspace. This scope is the key’s root, and it determines everything the key can reach.
  • A set of permissions. You select these individually from the permissions available at that scope. Nothing is selected by default.
  • An expiration date. Required, and capped at 365 days.
None of the three can be changed afterward. To adjust a key’s permissions or move it to a different scope, revoke it and create a replacement. Fine-grained keys authenticate the HoneyHive control plane, sent as a bearer token in the Authorization header. The endpoints that manage projects and alerts accept fine-grained keys only, so a project API key is rejected there.

What a fine-grained key can reach

A key reaches its root scope and every scope beneath it, and nothing outside it. For example, a key rooted at a workspace can act on that workspace and on every project inside it, but not on the parent organization or on anything in a sibling workspace. A key rooted at an organization reaches every workspace and project in that organization. Coverage is evaluated on every request, not fixed at creation. A project created after the key was issued is covered automatically, with no change to the key. Archived scopes drop out of coverage. The root also bounds which permissions the key can be given: the create-key dialog only offers permissions that apply at the root scope or below, so a workspace-rooted key is never offered organization-level permissions.
Because a key covers all current and future descendants of its root, prefer the narrowest root that still works. A key that only manages one team’s projects belongs on that team’s workspace, not on the organization.

Creating a fine-grained key

You need permission to create keys on the scope you are creating them for. Org Admins can create organization-rooted keys, and Workspace Admins can create workspace-rooted keys. See Permission Reference.
1

Open the API Keys settings for the scope

For a workspace-rooted key, go to Settings > Workspace > API Keys. For an organization-rooted key, go to Settings > Organization > API Keys.
2

Click Create API Key

Give the key a name that identifies the workload using it, for example ci-project-provisioning. The description is optional. Use it to explain the key’s purpose to whoever inherits it.
3

Set an expiration

Choose one of the presets or a custom date. The default is 90 days and the maximum is 365 days. Plan to create the replacement key before this date.
4

Select permissions

Check only the permissions the workload needs. You cannot add permissions later.
5

Copy the key

Click Create Key, then copy the full key value from the dialog and store it in your secret manager. This is the only time the value is shown. HoneyHive stores only a hash of it, so it cannot be recovered or displayed again.
After creation, the key list shows each key as hh_fgcp_<key id>_******. The visible portion is the key’s id, not part of its secret, so you can match a key in the list to a key in your logs without exposing anything sensitive.

Revoking a fine-grained key

Open the API Keys page for the scope the key is rooted on and revoke it from the key’s row. Revoking a fine-grained key takes effect immediately. The next request made with that key fails. Revoked and expired keys stay in the list, marked as revoked or expired, alongside who created them, who revoked them, and when. This history lets you audit key usage, including after someone leaves the team, so the list is not meant to be pruned. To rotate a key, create the replacement first, move your workload over to it, then revoke the old key.

Restricting what fine-grained keys can carry

Organizations can narrow the permissions anyone is allowed to put on a fine-grained key. Go to Settings > Organization > API Key Policy and select the permissions that keys in this organization may carry. Anything you leave out is unavailable in every create-key dialog, at every scope in the organization. This is useful when workspace admins can mint their own keys but your security team wants to bound what those keys can ever do. Changing the policy requires permission to manage role definitions, which workspace admins do not have, so the limit holds even though they are the ones creating keys. Two things to know:
  • By default no restriction is applied, and the full set of available permissions is offered.
  • The policy applies when a key is created. Narrowing it does not change or revoke keys that already exist. To withdraw a permission from an existing key, revoke that key directly.

Ingestion keys

An ingestion key does one job: it lets the HoneyHive tracer SDKs and OTLP exporters send traces and events to a single project. It carries no other capability, which makes it the key to deploy on production servers, where a leaked credential should not be able to read anything back.

What an ingestion key can reach

An ingestion key is bound to exactly one project and authenticates only that project’s ingestion endpoints: the OpenTelemetry traces endpoint and the endpoints that create sessions and create or update events, singly or in batches. That is the whole path the HoneyHive tracer and OTLP exporters use, so tracing works with an ingestion key alone. Every other data plane endpoint rejects an ingestion key with a 404. Reading events, running experiments with evaluate(), and managing datasets need a project API key, as does any API client call outside the ingestion operations above. A service that both sends telemetry and reads it back uses two keys, and the one on the hot path carries no read access. The data plane clients hold both at once; see Using an ingestion key with the SDKs.

Why ingestion keys never expire

Ingestion keys have no expiration date. They are deployed across fleets of servers and exporters, and a key that expired on a timer would stop telemetry from every one of them at once, silently. Revocation is the only way an ingestion key stops working. To rotate an ingestion key, create the replacement, move your fleet over to it, then revoke the old key.

Creating an ingestion key

You need project.ingestion_api_key.post on the project, plus .list to open the Ingestion tab. The default Project Admin role carries all four ingestion key permissions, and a custom role can too. Project Member carries .get and .list, so members see the Ingestion tab and its keys but cannot create one. See Permission Reference.
1

Open the project's API Keys settings

Go to Settings > Project > API Keys. The page opens on the Ingestion tab. Project API keys live on the Project tab beside it.
2

Click Create API Key

Give the key a name that identifies the fleet or service using it, for example prod-web-servers. The description is optional. Use it to record where the key is deployed.
3

Copy the key

Click Create Key, then copy the full key value and store it where your application runs, as HH_INGESTION_API_KEY in your secret manager. This is the only time the value is shown. HoneyHive stores only a hash of it, so it cannot be recovered or displayed again.
The Ingestion tab also shows your project’s data plane URL. Where it differs from the SDK default, set it as HH_API_URL for the Python SDK or HH_DATA_PLANE_URL for the TypeScript client. OTLP exporters send to <data plane URL>/opentelemetry/v1/traces. After creation, the key list shows each key as hh_ingst_<key id>_******. As with fine-grained keys, the visible portion is the key’s id, not part of its secret, so you can match a key in the list to a key in your logs without exposing anything sensitive.

Using an ingestion key with the SDKs

The data plane clients (the Python SDK, the TypeScript API client, and the CLI) hold an ingestion key separately from a project key. The ingestion key goes in HH_INGESTION_API_KEY. The project key stays where it is today: HH_API_KEY for the Python SDK, HH_PROJECT_API_KEY for the TypeScript client and the CLI. Each call uses the key its endpoint accepts:
  • Ingestion calls (OTLP export, session start, and event writes) use the ingestion key when one is set, and the project key otherwise.
  • Every other call uses the project key. The ingestion key is never sent to those endpoints, so a process holding only an ingestion key gets a 404 from them.
A process that traces and runs experiments sets both variables: evaluate() sends its traces with the ingestion key and creates runs with the project key. A tracing-only process sets only HH_INGESTION_API_KEY. A project key alone keeps working everywhere, as it does today. HH_INGESTION_API_KEY is strict. Its value must be an hh_ingst_ key, and any other value raises when the tracer or client initializes, naming where the value came from and the expected prefix. The project key variable is not checked, so an ingestion key placed there is forwarded as-is: it works for sending traces and gets a 404 from everything else. The CLI checks before it sends. A non-ingestion data plane command run with only an ingestion key configured is refused with a message naming the key it needs, rather than reaching the server. The ingestion commands take either key. The control-plane SDK is separate. It takes only a fine-grained key in HH_CONTROL_PLANE_API_KEY, and neither a project key nor an ingestion key works there.

Revoking an ingestion key

Open Settings > Project > API Keys and revoke the key from its row on the Ingestion tab. Revoking requires the project.ingestion_api_key.delete permission, which the default Project Admin role carries and Project Member does not. Revocation takes effect within two minutes rather than immediately: ingestion verifies keys from a cache with a two-minute bound by default, so applications using the key stop sending telemetry within that window. Self-hosted deployments that tune the ingestion key cache get their configured window instead. Revoked keys stay in the list, marked as revoked, alongside who created them, who revoked them, and when.

Security guidance

  • Grant key creation deliberately. Someone who can create keys on a scope can issue a key that acts on every scope beneath it, including projects they cannot access themselves. Only grant this to people you would trust with that access directly.
  • One key per workload. Separate keys for separate systems keep the blast radius small and make it obvious which key to revoke.
  • Store keys in a secret manager. Never commit a key or paste it into application code.
  • Rotate on a schedule. Fine-grained keys expire, which gives you a natural rotation cadence. Replace them before they lapse rather than after a failure. Ingestion keys do not expire, so put their rotation on your own calendar.
  • Put ingestion keys, not project keys, on production servers. A server that only sends telemetry should hold a credential that can only send telemetry.

Roles and permissions

How permissions and roles work across scopes

Organization hierarchy

How organizations, workspaces, and projects nest

Managing projects

Create and organize projects

Alerts

Monitor cost, latency, errors, and evaluator scores

Log your first trace

Send a first trace with an ingestion key