Permissions
Lexabit resolves "can this request do this?" in four layers. Every scoped endpoint runs through them in order, and understanding the order is the fastest way to reason about why a call succeeded, returned less than you expected, or was rejected.
The four layers
| Layer | Question it answers | Fails with |
|---|---|---|
| 1. Authentication | Who are you? Is the bearer token valid? | 401 unauthenticated |
| 2. Visibility | What can you see? Which entities are reachable from your active scope? | Filtered out of lists; 404 not_found on direct access |
| 3. Entitlement | Are you allowed to use this capability at all? Does your role grant the permission this endpoint requires? | 403 forbidden |
| 4. Action | Are you allowed to do this specific thing to this specific entity? | 403 forbidden |
Read it as a funnel: authentication establishes who, scope + visibility narrow which entities are even in view, entitlement checks whether you hold the capability, and the action check applies it to this target.
1. Authentication
You present a bearer token (see Authentication). This establishes the acting user but says nothing about what they can see or do — that's the next three layers.
2. Visibility
Most endpoints operate inside an operating scope (the X-Scope header). An
entity is visible if it's reachable from that scope through the entity
hierarchy or an explicit grant. Visibility is why:
- List endpoints only return what's visible from the current scope — the
same token with a different
X-Scopereturns a different set. - Direct reads of an invisible entity return
404, not403. If you can't see it, the API won't even confirm it exists. (More on this below.)
See Scopes & Workspaces for how scope is set and how it narrows the hierarchy.
3. Entitlement
Being able to see an entity doesn't mean you can act on it. Each endpoint
declares the capability it needs (for example, "create clients" or "manage
consents"). Your role on the relevant entity grants a set of these
capabilities. If your role doesn't include the required one, the call fails
with 403 forbidden even though the entity is visible.
Roles are assigned per entity — a user can be an editor on one team and a viewer on another. See Users, Roles & Permissions for assigning roles and inspecting effective permissions.
4. Action
The final layer applies the capability to the concrete target: some actions
depend on entity state or relationship (for example, you may be entitled to
"close cases" in general, but not a case that's already archived, or one you
have only read access to). When this check fails you again get
403 forbidden.
Worked example: 403 vs 404
The distinction trips up most newcomers, so it's worth making concrete.
Suppose case c-777 exists in your tenant.
-
You can see it, but lack the capability to delete cases →
DELETE /cases/v1/c-777returns:{"error": { "code": "forbidden", "message": "You do not have permission to delete this case." },"meta": { "requestId": "…" }} -
The case is outside your active scope (not visible) →
DELETE /cases/v1/c-777(or evenGET) returns:{"error": { "code": "not_found", "message": "Case not found." },"meta": { "requestId": "…" }}
Same endpoint, same case id — the difference is which layer rejected you. A
404 on something you're sure exists usually means a scope/visibility
problem (wrong or missing X-Scope), not a deleted record. A 403 means the
entity is visible but your role doesn't grant the action.
401? → token problem (layer 1).404on something that should exist? → checkX-Scope(layer 2).403? → your role lacks the capability, or the action isn't allowed on this target (layers 3–4). Inspect your effective permissions on the entity via the effective-permissions endpoint.
Checking effective permissions
To see exactly what a user can do on a given entity, ask the API directly rather than guessing:
GET /entitypermissions/v1/entities/{entityType}/{entityId}/users/{userId}/effective-permissions
It returns the resolved capability set for that user on that entity — the authoritative answer to "would this action be allowed?" without having to attempt it.
See also
- Scopes & Workspaces — the visibility layer in depth
- Users, Roles & Permissions — assigning roles
- Error Handling — reacting to
401/403/404in code