Skip to main content

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

LayerQuestion it answersFails with
1. AuthenticationWho are you? Is the bearer token valid?401 unauthenticated
2. VisibilityWhat can you see? Which entities are reachable from your active scope?Filtered out of lists; 404 not_found on direct access
3. EntitlementAre you allowed to use this capability at all? Does your role grant the permission this endpoint requires?403 forbidden
4. ActionAre 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-Scope returns a different set.
  • Direct reads of an invisible entity return 404, not 403. 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 casesDELETE /cases/v1/c-777 returns:

    {
    "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 even GET) 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.

Debugging access issues
  1. 401? → token problem (layer 1).
  2. 404 on something that should exist? → check X-Scope (layer 2).
  3. 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