Content-Type headers). All response bodies are JSON-encoded.
The API base URL for GrowthBook Cloud is https://api.growthbook.io/api. For self-hosted deployments, it is the same as your API_HOST environment variable (defaults to http://localhost:3100/api). The rest of these docs will assume you are using GrowthBook Cloud.
Versioning
Endpoints are versioned by path prefix:/v1/...— stable, widely-supported endpoints/v2/...— updated endpoints with improved shapes (e.g. unified per-rule environment scope for feature flags)
Authentication
We support both the HTTP Basic and Bearer authentication schemes for convenience. You first need to generate a new API Key in GrowthBook. Different keys have different permissions:- Personal Access Tokens: These are sensitive and provide the same level of access as the user has to an organization, or less if the token’s permissions are limited. These can be created by going to
Personal Access Tokensunder your user menu. Members with the API Keys Manage members’ tokens permission can disable a member’s token underSettings -> Manage PATs, and admins can require new tokens to expire within a maximum lifetime. - Secret Keys: These are sensitive and provide the level of access of the role they are given, which can be any built-in or custom role, with optional per-project role overrides and environment limits. Managing Secret Keys on behalf of an organization takes the API Keys permissions. These can be created by going to
Settings -> API Keys, where Admins can also require new Secret Keys to expire within a maximum lifetime.
: at the end of the secret to indicate an empty password)
X-GrowthBook-Key-Expires-At header (ISO 8601), so scripts can warn before the key stops working. Requests made with an expired key fail with a 401 that says where to create a replacement. See Expiration for choosing a key’s expiration, the warnings before it lapses, and the organization policies.
Naming who asked
Requests made with a Secret Key may add anX-GrowthBook-Requested-By header naming the organization member who asked for the change, as a user id or an email address. History, revision logs and webhooks show that member next to the key.
Each key’s settings under Settings -> API Keys:
- Header: Optional (the default) uses the header when it’s sent, Required rejects requests without it, and Rejected rejects requests that send it, each with a 400.
- Permissions, when a member is named:
- Assume member’s role (the default): the request acts as that member, with only what both the key and the member can do, so the header can narrow a key but never widen it. Drafts, owners,
minefilters and reviews are the member’s. The member’s rights over their own drafts, comments and verdicts apply only where the key’s own role allows the same action. - Use key’s role: the key acts as itself, with its own permissions, and the name is only recorded in history. Drafts, verdicts and ownership are the key’s, as when no member is named.
- Assume member’s role (the default): the request acts as that member, with only what both the key and the member can do, so the header can narrow a key but never widen it. Drafts, owners,
owner defaults it to the member whose role the key assumes. Scheduled and auto-publishes run later with the permissions of the request that armed them, and don’t run if that member has left the organization, the key has expired, or the key no longer assumes members’ roles. Personal Access Tokens and OAuth tokens already act as their user and reject the header.
Naming and human review
People review what the API creates in the GrowthBook UI.- Keep keys and names short (2-5 words). Follow your organization’s Feature Flag key format (
featureRegexValidatorandfeatureKeyExampleinGET /v1/settings), or use kebab-case if it has none. Feature Flag keys can’t be changed after creation, and an experiment’s tracking key shouldn’t change after launch. - Put context (why, plan, tickets, links) in
description, not in names or keys. - Group with
tags, not name prefixes. Projects (projectorprojects) control access and where a resource can be used, so set them deliberately instead of using them as labels. - To create a Feature Flag disabled with
POST /v2/features, list every environment inenvironmentswithenabled: false(onPOST /v1/features, each entry also needsrules: []). An environment you leave out uses its default state, which may be enabled. - Leave publishing and production changes to a person unless asked.
- If a request is blocked (an approval requirement, a warning, a Custom Hook, schema validation or a permission error), stop and ask a person. Don’t retry with an override field, a different key or another workaround unless a person asked you to. If a write answers
202with aconfirmation, give a person itsurland wait (see Waiting for confirmation).
Waiting for confirmation
A key can require a person to confirm some writes before they run (see API Keys for Agents). A held write doesn’t run. It answers202 Accepted with the confirmation, a Location header to poll, and a Retry-After header with the seconds to wait between polls:
url, then poll GET /v1/confirmations/{id}. Pass wait (in seconds, up to 30) to hold the poll open until the status changes:
note carries anything the person left for the agent when they decided. actions lists what the request was held for, each with the environments it touches.
- Only the key that made the request, or another token of the same person, can read the confirmation.
- Sending the same request again while it’s pending returns the same confirmation.
- A request that publishes, reverts or archives, or that changes a Feature Flag or an Experiment’s status, schedule, targeting or traffic, isn’t run if what it acts on changed after it was held. Other writes, such as editing settings or a draft, run as sent, so they can overwrite changes made while they waited.
- A confirmed request runs once, with the key’s permissions (or the member’s role it assumes), not the confirmer’s. Send it again to retry, which asks for a new confirmation.
- Confirming isn’t a review approval.
Errors
The API may return the following error status codes:- 400 - Bad Request - Often due to a missing required parameter
- 401 - Unauthorized - No valid API key provided
- 402 - Request Failed - The parameters are valid, but the request failed
- 403 - Forbidden - Provided API key does not have the required access
- 404 - Not Found - Unknown API route or requested resource
- 422 - Unprocessable Entity - The request is valid, but a warning, validation rule, approval requirement, or another publishing gate blocked it. Do not assume that
ignoreWarningsclears every 422 response. - 429 - Too Many Requests - You exceeded the rate limit of 60 requests per minute, or the limit your self-hosted server sets. Try again later.
- 5XX - Server Error - Something went wrong on GrowthBook’s end (these are rare)
- message - Information about the error
Publishing gates
Automated callers, including AI agents, should report a blocked response to a person instead of retrying with an override. Use an override only when a person has explicitly asked for it. Publish responses include agates array that explains every blocker:
type,severity, andmessagesidentify the problem.overridenames the request-body field that can bypass it. This isignoreWarningsfor warnings,skipSchemaValidationfor schema and invariant failures, orskipHooksfor Custom Hook rejections. A value ofnullmeans there is no request-body override.requiresPermissionidentifies any additional permission needed to use the override.resolutionprovides an API action, method, and path when the blocker must be resolved another way.
resolution.
When a successful publish bypasses a gate, the response includes bypassedGates. Each entry reports the gate type and how it was bypassed in via, which is one of ignoreWarnings, skipSchemaValidation, skipHooks, bypassApprovalPermission, restApiBypassesReviews, or revertsBypassApproval (reverts only). This field is omitted when no gates were bypassed.
