Admin API
Introduction
The Admin API is the HTTPS interface to everything you manage in the dashboard for a project: projects, environments, configs and their targeting rules, segments, and tags. The Terraform provider and the MCP server are built on it, and anything they can do, a script of yours can do too.
Every request goes through the same validations as the dashboard, so a value that the dashboard would refuse is refused here with the same message. Every change shows in the audit log with a source of API and the name of the token that made it.
The API describes itself with an OpenAPI 3.1 document, which needs no authentication:
https://api.configdirector.com/v1/openapi.json
It holds the exact request and response schema of every endpoint on this page, including the targeting rule and segment condition shapes, and the base URL below as its server, so it is the file to hand to an OpenAPI client generator.
Base URL
https://api.configdirector.com/v1
Requests and responses are JSON. Send Content-Type: application/json with every request that has a body. Projects, environments, and tags are addressed by their id, a UUID; configs and segments are addressed by their key, so a URL reads the way the dashboard does:
GET https://api.configdirector.com/v1/projects/{projectId}/configs/new-checkout
Authentication
Create an API token in the dashboard under API tokens and send it as a bearer token:
Authorization: Bearer YOUR-API-TOKEN
A token belongs to the member who created it, and only that member can see, rename, or revoke it. When it is created, it is given a subset of the permissions below, and it never has more than its creator's role grants, even if the role changes later. A token can have an expiration date, which is recommended for tokens stored on a workstation. Keep tokens out of source control, and provide them through an environment variable or a secret store.
A request that is not authenticated, or that the token's permissions do not allow, is refused with 403 and a body that says why:
{
"error": "The Authorization header is missing. Send `Authorization: Bearer <api token>`.",
"code": "AUTHORIZATION_HEADER_MISSING"
}
code | Meaning |
|---|---|
AUTHORIZATION_HEADER_MISSING | The request has no Authorization header. |
AUTHORIZATION_HEADER_INVALID | The header is not of the form Bearer <api token>. |
API_TOKEN_NOT_FOUND | No token matches. It may have been revoked, or its organization disabled. |
API_TOKEN_EXPIRED | The token's expiration date has passed. The message says when. Create a new token. |
API_TOKEN_OWNER_REMOVED | The member who created the token no longer belongs to the organization. Create a new token. |
INSUFFICIENT_PERMISSIONS | The token is valid but lacks the permission the endpoint needs. The endpoint table below names each one. |
Permissions
Each endpoint needs one permission, named in the endpoints table. The permissions the Admin API uses are:
| Resource | Permissions |
|---|---|
| Projects | projects:read, projects:create, projects:update, projects:delete |
| Environments | environments:read, environments:create, environments:update, environments:delete |
| Configs | configs:read, configs:create, config-settings:update, config-targeting-rules:update, configs:archive |
| Segments | segments:read, segments:create, segments:update, segments:delete |
| Tags | tags:read, tags:create, tags:update, tags:delete |
Creating a config with tags needs config-settings:update as well as configs:create. Members, API tokens, SDK keys, contexts, and the audit log are managed in the dashboard only.
Terraform, OpenTofu, and the audit log
Every change made through the API is recorded in the audit log with the source API and the token's name. A client that is Terraform or OpenTofu says so with the X-SourceClient header, whose accepted values are terraform and opentofu, so the audit log shows which one made the change. Any other value is recorded as API. The Terraform provider sends the header for you.
Responses and errors
| Status | When |
|---|---|
200 | The request succeeded and the body holds the resource. |
204 | The request succeeded and there is nothing to return: updating a project or targeting rules, archiving a config, and deletions. |
400 | The body failed validation. The response lists each problem, with the field it concerns when there is one. A config key that is already in use in the project is reported this way too. |
403 | Not authenticated, or the token lacks the permission. See Authentication. |
404 | No resource with that id or key exists in the project or organization. |
409 | Deleting a segment that the targeting rules of a config still use. The body's usages lists each config and the environments whose rules use it. |
413 | The request body is larger than 4 MB. |
429 | Service is suspended, because a Free organization has stayed over its free allowance past the billing grace period or a Pay as you go organization has reached its spending limit. The body is { "error": "Service suspended", "code": "SERVICE_SUSPENDED" } with a Retry-After header. A Free organization that has used up an hourly JSON Schema budget gets 429 too, with a message that says when the budget resets. |
A 400 body:
{
"errors": [
{ "name": "key", "message": "The key must be at least 4 characters long" }
]
}
Usage
Each request counts as one Admin API request against your organization's monthly free allowance of 10,000, and beyond it at the Pay as you go rates. Terraform applies and MCP tool calls count the same way, since both go through the API. Reading the OpenAPI document is free.
Endpoints
Projects
| Method | Path | What it does | Permission |
|---|---|---|---|
GET | /projects | List the organization's projects, without their environments. | projects:read |
POST | /projects | Create a project from a name and a slug. Returns it with its environments, Test and Production. | projects:create |
GET | /projects/{projectId} | Get a project with its environments. | projects:read |
PUT | /projects/{projectId} | Rename a project or change its slug. | projects:update |
DELETE | /projects/{projectId} | Delete a project with everything in it. | projects:delete |
Environments
| Method | Path | What it does | Permission |
|---|---|---|---|
GET | /projects/{projectId}/environments | List the project's environments. | environments:read |
POST | /projects/{projectId}/environments | Create an environment from a name, a slug, a color, and whether it is live. | environments:create |
GET | /projects/{projectId}/environments/{environmentId} | Get an environment. | environments:read |
PUT | /projects/{projectId}/environments/{environmentId} | Update an environment's name, slug, color, or live flag. | environments:update |
DELETE | /projects/{projectId}/environments/{environmentId} | Delete an environment and everything in it. | environments:delete |
Configs
| Method | Path | What it does | Permission |
|---|---|---|---|
GET | /projects/{projectId}/configs | List the project's configs, without targeting rules. Repeat tagIds to list the configs that have any of those tags, or send untagged=true for the configs without tags. | configs:read |
POST | /projects/{projectId}/configs | Create a config from its key, role, lifetime, type, and defaultValue, which becomes the default targeting rule value in every environment. Optional: description, typeOptions for the type's constraints, client and server availability, variations, and tagIds. | configs:create |
GET | /projects/{projectId}/configs/{configKey} | Get a config with its targeting rules in every environment. | configs:read |
PATCH | /projects/{projectId}/configs/{configKey} | Update the config's settings: key, description, role, lifetime, type, typeOptions, variations, availability, or tagIds. Only the fields sent change. | config-settings:update |
PUT | /projects/{projectId}/configs/{configKey}/targets | Replace the targeting rules of one environment. See Updating targeting rules. | config-targeting-rules:update |
GET | /projects/{projectId}/configs/{configKey}/activity | The time of the most recent evaluation per environment, SDK key kind, SDK name, and SDK version. | configs:read |
DELETE | /projects/{projectId}/configs/{configKey} | Archive the config. It can be restored from the dashboard for 30 days. | configs:archive |
A config's type is one of boolean, string, integer, float, enum, url, json, or timespan, and its role is config, flag, kill-switch, or experiment. typeOptions carries the constraints of the type: isInteger, min, and max for numbers, values and valueType for an enum, useSchema and schema for JSON, unit, min, max, and allowFractions for a timespan, and secureOnly for a URL. Configs Anatomy explains each.
Segments
| Method | Path | What it does | Permission |
|---|---|---|---|
GET | /projects/{projectId}/segments | List the project's segments, each with the configs and environments whose rules use it. | segments:read |
POST | /projects/{projectId}/segments | Create a segment from a key, a name, its condition groups, and optional environment overrides, a map from environment id to that environment's own groups. | segments:create |
GET | /projects/{projectId}/segments/{segmentKey} | Get a segment. | segments:read |
PUT | /projects/{projectId}/segments/{segmentKey} | Replace the segment's key, name, and groups. When overrides is sent, the environment overrides become exactly that map, so {} removes them all; when it is left out, they stay. | segments:update |
DELETE | /projects/{projectId}/segments/{segmentKey} | Delete the segment and its overrides. Refused with 409 while any config's rules use it. | segments:delete |
Tags
| Method | Path | What it does | Permission |
|---|---|---|---|
GET | /projects/{projectId}/tags | List the project's tags by name. | tags:read |
POST | /projects/{projectId}/tags | Create a tag. Names are trimmed, 1 to 50 characters, and unique in the project ignoring case. | tags:create |
GET | /projects/{projectId}/tags/by-name | Find a tag by name, ignoring surrounding whitespace and case. | tags:read |
GET | /projects/{projectId}/tags/{tagId} | Get a tag. | tags:read |
PUT | /projects/{projectId}/tags/{tagId} | Rename a tag. Its id, and every config assignment, stay the same. | tags:update |
DELETE | /projects/{projectId}/tags/{tagId} | Delete a tag. Configs that had it lose the assignment. | tags:delete |
Examples
List the projects of the organization:
curl https://api.configdirector.com/v1/projects \
-H "Authorization: Bearer ${CONFIGDIRECTOR_TOKEN}"
Create a temporary feature flag that starts off in every environment:
curl -X POST https://api.configdirector.com/v1/projects/${PROJECT_ID}/configs \
-H "Authorization: Bearer ${CONFIGDIRECTOR_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"key": "new-checkout",
"description": "The redesigned checkout flow",
"role": "flag",
"lifetime": "temporary",
"type": "boolean",
"defaultValue": false
}'
Updating targeting rules
PUT /projects/{projectId}/configs/{configKey}/targets replaces the rules of one environment. The body names the environment, the default targeting rule value, and the rules in order. Each rule, condition, and percentage carries an id, a UUID you generate.
A conditional rule serves true to two named users, and the default targeting rule serves false to everyone else:
curl -X PUT https://api.configdirector.com/v1/projects/${PROJECT_ID}/configs/new-checkout/targets \
-H "Authorization: Bearer ${CONFIGDIRECTOR_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"environmentId": "'"${ENVIRONMENT_ID}"'",
"defaultValue": false,
"rules": [
{
"id": "7a6b0d1e-3b4e-4a8e-9c3b-1f2e3d4c5b6a",
"type": "conditional",
"order": 0,
"target": "value",
"value": true,
"conditions": [
{
"id": "0c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
"kind": "attribute",
"attribute": "identifier",
"operator": "is one of",
"targetType": "text",
"targetValues": ["user-101", "user-202"]
}
]
}
]
}'
A rule has a type of conditional or percentage. A conditional rule holds conditions, every one of which must match, and either a target of value with the value to serve or a target of percentage with percentages, a list of { id, percentage, value } that adds up to 100. A percentage rule holds only percentages. An attribute condition tests identifier, kind, name, appName, appVersion, or traits with a trait JSON pointer, read as the targetType text, number, semver, datetime, array, or boolean, each with its own operators. A segment condition is { id, kind: "segment", operator: "in" | "not in", segmentId }. The OpenAPI document lists every operator per target type, and the Terraform provider page shows the same rules in HCL.
Rules are validated against the config's type and constraints before they are saved, exactly as in the dashboard: a value outside an integer's range, a URL that is not HTTPS on a secure-only config, or a JSON value that fails the config's schema is refused with 400.
MCP
Manage projects, configs, targeting rules, and segments from AI coding tools through the Model Context Protocol
From LaunchDarkly
Move your feature flags from LaunchDarkly to ConfigDirector. How projects, environments, flags, contexts, segments, and rollouts map, how to recreate the flags, and how to switch the SDKs over without a risky release.