Summary and recommendation
LaunchDarkly exposes a versioned REST API at https://app.launchdarkly.com/api/v2 authenticated via Bearer token (Authorization header). Member lifecycle operations - list, create, update role, delete - map to /api/v2/members. All PATCH calls use JSON Patch (RFC 6902) array format, not merge-patch; sending a plain JSON object body will fail.
Pin the API version using the LD-API-Version request header (e.g., 20220603) to avoid breaking changes on future releases.
The REST API access token and the SCIM bearer token are distinct credentials generated in different parts of the UI. Conflating them is a common integration error.
Rate limits default to 50 requests per 10 seconds per token across all plans; HTTP 429 responses include a Retry-After header and an X-Ratelimit-Reset Unix epoch timestamp (not a seconds-until-reset delta).
API quick reference
| Has user API | Yes |
| Auth method | API access token (Bearer token) passed in Authorization header |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise |
Authentication
Auth method: API access token (Bearer token) passed in Authorization header
Setup steps
- Log in to LaunchDarkly and navigate to Account Settings > Authorization.
- Click 'Create token' under 'Access tokens'.
- Choose token type: personal (scoped to your account) or service (for automation).
- Assign a built-in role (Reader, Writer, Admin, Owner) or a custom role.
- Copy the token immediately - it is not shown again.
- Pass the token in requests as: Authorization:
Required scopes
| Scope | Description | Required for |
|---|---|---|
| Admin or Owner role | Full access to account member management including create, update, delete | POST /members, PATCH /members/{id}, DELETE /members/{id} |
| Reader role | Read-only access to account members and teams | GET /members, GET /members/{id} |
| Custom role with member write actions | Granular policy-based access; actions include createMember, updateMemberRole, deleteMember | Fine-grained member management without full Admin |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| _id | string | System-generated unique member ID | auto-generated | immutable | Used as path parameter in member-specific endpoints |
| string | Member's email address; used as login identifier | required | not updatable via API | Must be unique within the account | |
| firstName | string | Member's first name | optional | patchable | |
| lastName | string | Member's last name | optional | patchable | |
| role | string (enum) | Built-in role: reader, writer, admin, owner | required (or customRoles) | patchable | Mutually exclusive with customRoles at the top level |
| customRoles | array of strings | List of custom role keys assigned to the member | optional | patchable | Requires custom roles feature; overrides built-in role assignment |
| teamKeys | array of strings | Keys of teams the member belongs to | optional | managed via /teams endpoints | Read from member object; write via team membership endpoints |
| verified | boolean | Whether the member has verified their email | auto-set | immutable | |
| pendingInvite | boolean | True if the member has not yet accepted their invitation | auto-set | immutable | |
| mfa | string (enum) | MFA status: enabled or disabled | auto-set | immutable via API | Managed by the member themselves or SSO enforcement |
| excludedDashboards | array of strings | Dashboards excluded from the member's view | optional | patchable | |
| _lastSeen | integer (Unix ms) | Timestamp of last login | auto-set | immutable | |
| _creationDate | integer (Unix ms) | Timestamp when the member was created | auto-set | immutable |
Core endpoints
List account members
- Method: GET
- URL:
https://app.launchdarkly.com/api/v2/members - Watch out for: Results are paginated; use offset+limit to page through all members. Default page size is 20.
Request example
GET /api/v2/members?limit=20&offset=0
Authorization: <token>
LD-API-Version: 20220603
Response example
{
"items": [{"_id":"abc123","email":"user@example.com","role":"writer"}],
"totalCount": 42,
"_links": {"next":{"href":"/api/v2/members?offset=20"}}
}
Get a single account member
- Method: GET
- URL:
https://app.launchdarkly.com/api/v2/members/{id} - Watch out for: Use the system _id, not email, as the path parameter.
Request example
GET /api/v2/members/abc123
Authorization: <token>
Response example
{
"_id": "abc123",
"email": "user@example.com",
"firstName": "Jane",
"lastName": "Doe",
"role": "writer",
"verified": true
}
Invite / create new members
- Method: POST
- URL:
https://app.launchdarkly.com/api/v2/members - Watch out for: Request body is an array - multiple members can be invited in one call. Invited members receive an email and appear with pendingInvite: true until accepted.
Request example
POST /api/v2/members
Content-Type: application/json
[{"email":"new@example.com","role":"reader",
"firstName":"New","lastName":"User"}]
Response example
{
"items": [{"_id":"xyz789","email":"new@example.com",
"role":"reader","pendingInvite":true}]
}
Update member role or attributes
- Method: PATCH
- URL:
https://app.launchdarkly.com/api/v2/members/{id} - Watch out for: Uses JSON Patch (RFC 6902) format - body must be an array of patch operations. Email cannot be changed via PATCH.
Request example
PATCH /api/v2/members/abc123
Content-Type: application/json
[{"op":"replace","path":"/role","value":"admin"}]
Response example
{
"_id": "abc123",
"email": "user@example.com",
"role": "admin"
}
Delete a member
- Method: DELETE
- URL:
https://app.launchdarkly.com/api/v2/members/{id} - Watch out for: Deleting a member is irreversible. The last Owner of an account cannot be deleted.
Request example
DELETE /api/v2/members/abc123
Authorization: <token>
Response example
HTTP 204 No Content
List teams
- Method: GET
- URL:
https://app.launchdarkly.com/api/v2/teams - Watch out for: Teams are an Enterprise/Pro feature. Team membership is managed separately from member role assignments.
Request example
GET /api/v2/teams?limit=20
Authorization: <token>
Response example
{
"items": [{"key":"eng-team","name":"Engineering",
"memberCount":12}],
"totalCount": 5
}
Add members to a team
- Method: POST
- URL:
https://app.launchdarkly.com/api/v2/teams/{teamKey}/members - Watch out for: Use member _id values (not emails) in memberIDs array.
Request example
POST /api/v2/teams/eng-team/members
Content-Type: application/json
{"memberIDs":["abc123","def456"]}
Response example
{
"key": "eng-team",
"name": "Engineering",
"memberCount": 14
}
Get SCIM user (via SCIM API)
- Method: GET
- URL:
https://app.launchdarkly.com/trust/scim/v2/Users/{id} - Watch out for: SCIM uses a separate bearer token generated in LaunchDarkly's SSO/SCIM settings, not the standard API access token.
Request example
GET /trust/scim/v2/Users/scim-user-id
Authorization: Bearer <scim-token>
Response example
{
"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"id":"scim-user-id",
"userName":"user@example.com",
"active":true
}
Rate limits, pagination, and events
- Rate limits: LaunchDarkly enforces per-token rate limits on REST API requests. Limits vary by plan. Response headers communicate current limit status.
- Rate-limit headers: Yes
- Retry-After header: Yes
- Rate-limit notes: Headers returned: X-Ratelimit-Limit, X-Ratelimit-Remaining, X-Ratelimit-Reset (Unix epoch seconds). HTTP 429 returned when exceeded. Retry-After header included on 429 responses.
- Pagination method: offset
- Default page size: 20
- Max page size: 100
- Pagination pointer: limit / offset
| Plan | Limit | Concurrent |
|---|---|---|
| All plans (default) | 50 requests per 10 seconds per token | 0 |
| Enterprise | Higher limits available; contact LaunchDarkly support for specifics | 0 |
- Webhooks available: Yes
- Webhook notes: LaunchDarkly supports outbound webhooks that fire on audit log events, including member and team changes. Webhooks are configured in Account Settings > Integrations > Webhooks.
- Alternative event strategy: LaunchDarkly also supports integrations via Slack, Datadog, and other platforms through its native integrations catalog for event-driven notifications.
- Webhook events: member created, member updated (role change), member deleted, team created, team updated, team deleted, custom role created/updated/deleted
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise
Supported operations: GET /Users - list users, GET /Users/{id} - get user, POST /Users - provision user, PUT /Users/{id} - replace user, PATCH /Users/{id} - update user attributes or deactivate, DELETE /Users/{id} - deprovision user, GET /Groups - list groups (teams), POST /Groups - create group, PATCH /Groups/{id} - update group membership, DELETE /Groups/{id} - delete group
Limitations:
- Requires Enterprise plan
- SSO must be configured before enabling SCIM
- Team sync (Groups) is only supported with Okta; other IdPs support user provisioning only
- SCIM token is separate from REST API access tokens - generated in SSO settings
- Only one SCIM token can be active at a time; regenerating invalidates the previous token
- Email (userName) cannot be changed via SCIM after provisioning
Common scenarios
Provisioning a new member: POST /api/v2/members with an array body containing email, firstName, lastName, and role (or customRoles for Enterprise). Capture _id from the response, then POST /api/v2/teams/{teamKey}/members with that _id to assign team membership. The member will carry pendingInvite: true until they accept the invitation email; team assignment succeeds immediately regardless of invite status.
Deprovisioning a departing member: GET /api/v2/members with a filter on email to retrieve _id, then DELETE /api/v2/members/{id}. Deletion is immediate and irreversible - no soft-delete or grace period exists. If the member holds the sole Owner role, the DELETE returns HTTP 400; ownership must be transferred to another Admin before the call will succeed. Personal API tokens belonging to the deleted member are invalidated instantly, breaking any automation that relied on them.
For full lifecycle automation, the SCIM 2.0 API at https://app.launchdarkly.com/trust/scim/v2 supports provisioning, deprovisioning, and group (team) sync - but group sync is limited to Okta. Entra ID, Google Workspace, and OneLogin support user provisioning only via SCIM. Only one SCIM token can be active at a time; regenerating it immediately invalidates the previous token and breaks the IdP integration until the new token is updated on the IdP side.
Provision a new employee and assign to a team
- POST /api/v2/members with email, firstName, lastName, and role (or customRoles).
- Capture the _id from the response.
- POST /api/v2/teams/{teamKey}/members with the new member's _id in the memberIDs array.
- Verify membership with GET /api/v2/members/{id} and check teamKeys field.
Watch out for: The member will have pendingInvite: true until they accept the email invitation. Team assignment succeeds immediately regardless of invite status.
Deprovision a departing employee
- GET /api/v2/members?filter=email:{email} to look up the member's _id.
- Optionally PATCH /api/v2/members/{id} to downgrade role to reader before deletion.
- DELETE /api/v2/members/{id} to remove the member from the account.
- Confirm with GET /api/v2/members/{id} - expect 404.
Watch out for: Deletion is immediate and irreversible. If the member is the sole Owner, the DELETE will fail with 400. Transfer ownership first.
Automate user lifecycle via SCIM with Okta
- Ensure Enterprise plan is active and SSO (SAML) is configured in LaunchDarkly.
- In LaunchDarkly Account Settings > Security, enable SCIM and copy the generated SCIM bearer token.
- In Okta, configure the LaunchDarkly SCIM app with base URL https://app.launchdarkly.com/trust/scim/v2 and the bearer token.
- Enable provisioning features in Okta: Push Users, Push Groups (for team sync).
- Assign users and groups in Okta; SCIM will provision/deprovision members and sync team membership automatically.
Watch out for: Group push (team sync) only works with Okta. Regenerating the SCIM token in LaunchDarkly immediately invalidates the old token and breaks the Okta integration until updated.
Why building this yourself is a trap
LaunchDarkly's member API integrates cleanly into an identity graph when _id, email, teamKeys, customRoles, _lastSeen, and pendingInvite fields are captured and correlated against your authoritative identity source.
The _lastSeen field (Unix milliseconds) is the only programmatic signal for detecting inactive accounts - it is absent from the UI but available via GET /api/v2/members/{id}, making API-driven access reviews the only reliable path for seat hygiene at scale.
The primary architectural trap is assuming SCIM Groups cover all IdPs. Building an automation that relies on group push for team membership will silently fail for any IdP other than Okta - the SCIM /Groups endpoints exist but are non-functional for non-Okta providers.
Teams using Entra ID or Google Workspace must handle team membership via direct REST API calls to /api/v2/teams/{teamKey}/members, which requires maintaining a separate mapping layer between IdP group membership and LaunchDarkly team keys. Factor this into any identity graph design that needs to reflect team-scoped flag permissions accurately.
Automate Launch Darkly workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.