- 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. Control plane keys can be rooted at an organization or workspace. Data plane keys can also be rooted at a project. The root 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.
Authorization header:
- Control plane keys (
hh_fgcp_) manage projects and alerts. SetHH_CONTROL_PLANE_API_KEYfor the control-plane SDK or CLI. - Data plane keys (
hh_fgdp_) read and manage project data through supported endpoints. SetHH_DATA_PLANE_API_KEYand pass the targetproject_idto each supported SDK call, or--project-idto the CLI. Even a project-rooted key needs the project ID in the request.
Supported data plane operations
Data plane keys authenticate the project-scoped endpoints under/v1/projects/{project_id}/. Each endpoint requires the listed permission on the key:
Adding datapoints to a dataset is gated on
project.dataset.post, not project.datapoint.post. The create-key dialog offers the permissions available for your scope and organization policy.
These endpoints replace the deprecated /v1/charts, GET /v1/datasets, DELETE /v1/datasets/{dataset_id}, POST /v1/datasets/{dataset_id}/datapoints, and GET /v1/datapoints/{datapoint_id} routes. The deprecated routes still accept classic project keys but reject data plane keys, and the project-scoped endpoints reject classic project keys. Both answer 404, so moving a call to the new endpoint means changing the key and the URL together.
An organization-rooted data plane key can also create project-rooted data plane keys with project.fine_grained_api_key_dp.post, and ingestion keys with project.ingestion_api_key.post. A key with either permission can carry only these key-creation permissions. Keys it creates cannot create more keys. See programmatic key creation for setup and examples.
Other non-ingestion data plane operations, including creating and updating datasets, creating, updating, and deleting individual datapoints, event reads, and experiment runs, still require a project API key. Keep that key configured for calls that need it. Adding HH_DATA_PLANE_API_KEY does not change which credential those calls send. Manage existing keys in Settings because data plane keys cannot list or revoke them.
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 project-rooted data plane key reaches only that project. Access always requires the corresponding permission on the key. An organization-rooted control plane key reaches the organization’s descendants across data planes. A data plane key is stored on one physical data plane and works only there, including when its root is an organization. If your organization spans multiple physical data planes, create a separate key on each one you need to access and send requests to that plane’s URL. 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 on its plane, prefer the narrowest root that works. A workload that accesses one project’s charts can use a project-rooted data plane key.
Creating a fine-grained key
You need the key family’s.list permission to open its tab, .post to create a key, and .delete to revoke one, at the key’s root scope:
Default Org Admin, Workspace Admin, and Project Admin roles carry the management permissions at their respective scopes. Project Member carries only
.get and .list for data plane keys, so members can view them but cannot create or revoke them. See Permission Reference.
Existing organizations do not automatically receive new role permissions. If the Data Plane tab is unavailable or its create/revoke controls are disabled, an organization admin must add the relevant
fine_grained_api_key_dp permissions under Settings > Organization > Roles to the roles that need them (for example, ProjectAdmin and/or ProjectMember).1
Open the API Keys settings for the scope
Go to Settings > Project, Workspace, or Organization > API Keys, depending on the root you need. Select Data Plane or Control Plane. At project scope, choose Data Plane for fine-grained keys or Project for classic keys.On the organization’s Data Plane tab, select the physical data plane if a selector appears. The key will work only on that plane.
2
Click Create API Key
Give the key a name that identifies the workload using it, for example
chart-reporting. 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.
hh_fgcp_<key id>_****** or hh_fgdp_<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.
Each page lists keys rooted at that scope. Manage workspace- and organization-rooted keys in their own settings, even when those keys also cover a project.
Using a data plane key
For this example, create a data plane key withproject.chart.list and set its full value in HH_DATA_PLANE_API_KEY. Copy the Project ID and Data plane URL from the project’s Data Plane tab. Set PROJECT_ID to that ID. If your URL differs from the default, set HH_API_URL for Python or HH_DATA_PLANE_URL for TypeScript and the CLI.
For SDK methods with both a legacy and a project-scoped route,
project_id selects the route and credential. These are the chart methods, datasets.list, datasets.delete, datasets.add_datapoints (addDatapoints in TypeScript, datasets add-datapoints in the CLI), and datapoints.get:
Calling these methods without
project_id is deprecated. Migrate it by configuring the data plane key and passing the project ID together. A classic project key cannot authenticate the scoped route, and a data plane key cannot authenticate the legacy route.
HH_DATA_PLANE_API_KEY is strict: it must contain a complete hh_fgdp_ key. A wrong key type or truncated value raises when the client initializes, even if the process does not call a method that uses it. Missing credentials are checked per call.
If an authenticated request returns 404, check the data plane URL, project ID, key root, selected permissions, expiration, and revocation status. Authorization denials and missing resources use the same 404 response.
Organization data plane visibility
The organization Data Plane tabs on API Keys and API Key Policy list only the data planes the signed-in user reaches through a workspace membership or a role permission below the organization. With only organization-level grants, you can see No data plane visible, even though the API would serve your keys on that plane. Ask an organization admin to grant the appropriate workspace membership or access below the organization. An empty selector does not mean the organization has no data plane or no keys. Multiple virtual data planes hosted on one physical data plane share one organization key list and one policy.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, choose Control Plane or Data Plane, and select the allowed permissions. Anything you leave out is unavailable when creating keys governed by that policy. The control plane policy and data plane policies are independent. On the Data Plane tab, select the physical data plane if a selector appears. That policy applies to all organization-, workspace-, and project-rooted data plane keys created on the selected plane only. This is useful when workspace or project admins can mint their own keys but your security team wants to bound their permissions. You needorg.roles.get to read the policy and org.roles.set to change it. See custom roles.
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 a404. Use a data plane key for supported operations. Reading events, running experiments with evaluate(), and creating or updating datasets still need a project API key. See Using an ingestion key with the SDKs for configuring these credentials separately.
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 needproject.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.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 ingestion, data plane, and project keys separately. The ingestion key goes inHH_INGESTION_API_KEY. The project key stays in HH_API_KEY for Python or HH_PROJECT_API_KEY for TypeScript 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.
- Supported project-scoped calls use
HH_DATA_PLANE_API_KEYand require a project ID. - Other calls use the project key. If the required credential is absent, the SDK or CLI fails before sending the request.
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.
HH_INGESTION_API_KEY is strict. Its value must be a complete hh_ingst_ key, and a wrong key type or incomplete value raises when the tracer or client initializes. Use the typed variable so format mistakes are caught at initialization.
An ingestion key placed in the unchecked project-key variable is forwarded by calls that use that credential: ingestion requests succeed, while non-ingestion requests sent with it return 404. Supported project-scoped calls still require a data plane key and fail before sending if it is missing.
The control-plane SDK is separate. It takes only a control plane fine-grained key in HH_CONTROL_PLANE_API_KEY.
Revoking an ingestion key
Open Settings > Project > API Keys and revoke the key from its row on the Ingestion tab. Revoking requires theproject.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 store key values in plaintext database rows, files, source code, or logs.
- 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.
Related
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