Available on Enterprise plans. An organization without an Enterprise plan is refused with HTTP
402 and the error code
enterprise_plan_required. Self-hosted deployments need an Enterprise
license for the same endpoints. To enable it, reach out to
enterprise@langwatch.ai.Intro
A role binding is one sentence: this principal has this role, here. It is how every kind of access in LangWatch is expressed, so this is the API to read when you want to know who can reach what. Each binding names exactly one principal, and there are three kinds:Authentication
Requires an organization-level API key withorganization:manage. Pass it as a Bearer token:
Endpoints
GET filters on userId, groupId, apiKeyId, scopeType and scopeId, and pages with offset and limit. limit defaults to 50 and cannot exceed 200. totalCount counts the filtered set, not the organization.
Scopes
The roles are
ADMIN, MEMBER, VIEWER, and CUSTOM. CUSTOM carries a customRoleId from the Roles API, and is refused without one (custom_role_id_required).
Some permissions only mean something for the organization as a whole, membership and billing among them. Granting one through a team- or project-scoped binding is refused at write time with org_exclusive_permission_scope, rather than being accepted and quietly having no effect.
Creating twice makes two bindings
Each create makes its own binding with its own id, even when the same principal already holds the same role at the same scope. A provisioning tool that must not duplicate should list first, or move to the Grants API, whose create takes anIdempotency-Key. A PATCH changes the role; the principal and the scope stay as they are, so moving a grant somewhere else means a new binding.
You cannot bind a role carrying a permission you do not hold yourself at that scope, and a request made with an API key is judged by the key’s own permissions. The refusal is 403 grant_exceeds_caller_permissions, with the permissions you lack in meta.missingPermissions. See Roles & access.
hasLegacyAccessNotice
A create response can carry hasLegacyAccessNotice: true. It means this is the person’s first explicit binding, and until now their access came from plain team membership, which this write switches off. No call failed and no call is blocked: it is there so a tool can tell an operator that this user’s access is now described entirely by bindings.
Errors
Migrating to grants
Grants and role bindings are the same records, so existing bindings appear inGET /api/v1/grants straight away and no copying is needed. Change the calls:
Grants also add an optional
expiresAt, a status filter, and an Idempotency-Key on create.