Organization Permission Management
Manage protected owners, permission groups, group membership, direct assignments, and authorized policy reads.
PixService separates the organization membership shell from protected ownership, permission groups, direct assignments, and the organization's entitlement ceiling. Membership alone does not grant access to protected resources.
Discover the permission catalog
Call GET /v1/permissions/catalog before building permission controls. The
catalog is code-owned and describes each stable capability key, binary or
tiered assignment values, valid organization/cluster/location scopes, optional
document-path support, evaluation contexts, hierarchy and visibility gates,
delegation metadata, entitlement controllability, valid ceilings, cleanup
actions, platform-only actions, and typed operational limits.
validMutationValues includes Inherit so clients can represent removal of a
manual override separately from the stored assignment values. Do not invent a
capability, scope, or value that is absent from the catalog.
Inspect your effective permissions
Use GET /v1/orgs/{organizationId}/permissions/effective to render actions for
the current user without permission-management authority. Supply
contextType=Organization, Cluster, Location, Bundle, Document, or
Job. Every context except Organization also requires its exact
resourceId. An organization, cluster, or location request may include a
case-preserving documentPath; the API normalizes separators and redundant
slashes before evaluating longest-path inheritance.
For example, this lookup evaluates a location and path:
GET /v1/orgs/{organizationId}/permissions/effective?contextType=Location&resourceId={locationId}&documentPath=/Contractor/Uploads
Authorization: Bearer {token}Bundle, Document, and Job identifiers are lookup contexts. The API resolves
their organization, cluster, location, and stored document path; it does not
create or report an individual-resource ACL. A visible cluster remains
inspectable when ClusterView survives even if OrganizationView does not.
Hidden, foreign, and nonexistent contexts all return the same 404 response.
The response reports the normalized context and, for each relevant capability,
the ordinary ACL result after principal-local visibility gates, the exact
organization entitlement ceiling, the current credential or PAT maximum, the
final value, blockedByEntitlement, visibility-gate outcomes, allowed actions,
and safe reason codes. Freshness includes permission and policy versions, exact
entitlement definition/version identity, operational usage markers, evaluation
time, and validUntilUtc. It never lists contributing groups, direct
assignments, another principal, internal reason messages, or raw credential
IDs. Even a permission manager uses the separate management endpoints below to
inspect assignments; current-user introspection does not change shape based on
management authority.
To evaluate an operation-dependent limit, optionally send storagePool with
requestedAdditionalBytes, requestedLogicalJobs,
requestedLifetimeLogicalJobs, requestedClusters, and/or
requestedLocations. Cluster and Location counts are organization-wide,
including when the evaluated Location belongs to one specific Cluster.
Detailed consumed, reserved, and remaining usage is included only when
OrganizationUsageView is present in the evaluated organization context. An
ordinary caller whose own operation is denied receives only the typed limit or
UTC reset boundary needed to explain that denial.
Use POST /v1/permissions/effective/batch for up to 100 contexts across one or
more organizations. Each item carries a unique correlationId and the same
context and optional operational fields as the single lookup:
{
"items": [
{
"correlationId": "11111111-1111-4111-8111-111111111111",
"organizationId": "22222222-2222-4222-8222-222222222222",
"contextType": "Location",
"resourceId": "33333333-3333-4333-8333-333333333333",
"documentPath": "/Contractor/Uploads"
}
]
}Results retain request order. A hidden item returns only its correlation and
isOpaque: true, with no normalized resource metadata. PAT organization scope
and capability maxima are evaluated independently for every item. Both lookup
forms are advisory for client rendering; every protected operation evaluates
current permissions again when it executes.
Inspect a member's organization-scope defaults
An authorized organization permission manager can inspect the backend-rendered organization-scope defaults for one selected member:
GET /v1/orgs/{organizationId}/permissions/effective/users/{userId}
Authorization: Bearer {token}This endpoint requires ManageOrganizationPermissions. It evaluates the
selected user as an ordinary interactive user. For every catalog capability
assignable at organization scope—including Cluster, Location, Document, and
Bundle capabilities whose final authorization requires a concrete resource—it
combines protected-owner, direct-user, and group values at organization scope
and applies the exact entitlement ceiling. The response intentionally excludes
cluster, location, and path overrides. It is an administration projection of
defaults, not proof of final access to any concrete resource; normal protected
operations still evaluate the resolved resource context and its visibility
gates. The endpoint does not reveal contributing assignment rows. A user
without a normal membership in the organization returns 404.
To label the result with current group membership, list the organization's
permission groups and their /{groupId}/members subresources. Do not combine
those rows with direct assignments in client code to infer effective access;
the selected-member endpoint remains the authoritative rendered result.
Clients must treat an unexpectedly omitted catalog capability as unevaluated,
not as an implicit None decision.
Understand asynchronous actor boundaries
Requester-visible background outputs—document-folder ZIPs, Bundle archive imports, and generated report PDFs—must retain an explicit requester or exact external-link actor. A system or migration identity cannot execute those task types. Their handlers still recheck current access before a result is attached where finalization attaches durable data, and every result retrieval rechecks current access before returning a URL or artifact.
Search indexing/backfills, search asset synchronization, chat synchronization, thumbnail derivation, organization-derived provisioning, and ZIP cleanup are maintenance task types. They cannot publish a direct task output URL or artifact pointer. When one is enqueued with a system identity, the credential ID and bounded policy key must match that exact maintenance type; process identity is never treated as a user.
Authorization-sensitive scheduled entitlement expiry and transition execution
use separate code-owned system credentials and policy keys, each scoped to the
single target organization. A differently keyed credential, another
organization scope, or an unbounded System actor is rejected before the
mutation. These system operations emit audit/outbox state but cannot create a
requester-visible result.
Treat authorization cache identities as bounded evidence
Within one request, PixService can reuse only an exact stable permission evaluation. Its identity includes the user and credential, PAT scope ceilings or bounded service policy, external-link authorization snapshot where applicable, organization permission version, exact immutable entitlement version and policy-catalog fingerprint, normalized resource/path context, and the earliest credential or entitlement validity boundary.
Storage, current Cluster/Location count, and monthly or lifetime Job usage are
evaluated after that stable stage. Derived-result identities include their
usage versions and freshness timestamps when those results are relevant. A
cache identity never extends validUntilUtc, and durable permission/policy
events remain the invalidation source for longer-lived projections.
Each delivered permission event advances durable, organization-scoped generations for evaluator decisions, authorized queries, ZIP/archive, thumbnail, report, search, chat/realtime, notification, and directory surfaces. Duplicate delivery of the same outbox generation is idempotent; operator replay advances a new generation. Long-lived caches and projection workers use the generation for their own surface, while request-scoped reads still evaluate the current permission and entitlement versions. Search suggestion and typo-vocabulary cache identities already include the durable Search generation, so a permission change cannot reuse a pre-change entry on another API process.
The invalidation generation is only a freshness marker, never authorization. Requester-bound generation/finalization and result retrieval continue to check the current actor, PAT, entitlement, resource, and capacity state. This also means a previously generated physical archive, thumbnail, or report may remain stored while current delivery is denied; stale storage never restores access.
The default operational objectives are 30 seconds from a committed change to durable invalidation for a change that may revoke access, and 120 seconds for general asynchronous propagation. Both values are deployment configuration and must be reviewed before Enforced cutover. Until a change is known to be expansion-only, it is measured against both objectives. These windows do not delay protected API reads or background finalization: those operations apply current authorization immediately on their next check.
Document-folder ZIPs use a different safe reuse rule: the cache correlation is derived from the exact authorized document set and each file revision, and the background payload stores those exact IDs. Two requesters may reuse the same archive only when that complete authorized snapshot is identical; a broader or newer set produces another archive identity.
Handle protected-operation denials
Centralized action enforcement returns 403 Forbidden with
code: "permission_action_denied" when the caller may know the target exists
but the current operation is not authorized. The response keeps requirement
classes separate so a client does not present an entitlement, PAT policy, or
capacity failure as an assignable ACL:
missingOrdinaryCapabilitiescontains capability keys and required/current values.entitlementCeilingscontains the organization policy ceiling separately.personalAccessTokenCeilingscontains PAT organization/scope or capability narrowing reasons.deploymentFeatures,storageCapacity,currentResourceCounts,monthlyJobAdmission, andlifetimeJobAdmissioncontain their typed prerequisite failures. Storage, Cluster, Location, monthly Job, and lifetime Job denials use the distinct stable codesstorage_capacity_exceeded,cluster_limit_exceeded,location_limit_exceeded,monthly_job_limit_exceeded, andlifetime_job_limit_exceeded. A depleted UTC-month allowance usesmonthly_job_limit_exceededand includes the bounded limit, remaining state, and reset boundary needed to explain the denied operation. Current resource counts and lifetime Job use never report a reset boundary.contextcontains only the normalized organization, cluster, location, resource, and path identifiers that are safe for that caller.
The denial does not include contributing groups, direct assignments, PAT IDs,
other principals, or detailed storage/job consumption. If confirming the
target would violate visibility, the same operation returns a metadata-free
404 instead: there is no denial code, context, missing-capability list, or
development exception marker to distinguish the target from a nonexistent
resource.
External share-link preflight uses the same safe ordinary, entitlement, and
credential distinction for every visible member of the proposed closure. It
does not report storage, current-resource, or Job admission because creating or
replacing share-link metadata consumes none of those limits. Operations that
do consume capacity expose those families through effective-permission probes
and the structured known-resource 403 response instead.
Query the permission audit log
Use GET /v1/orgs/{organizationId}/permission-audit to read immutable audit
events for one organization. The caller must be a protected owner or have a
final PermissionAuditLogView value of Allow; ordinary organization
membership and a platform administrator identity do not bypass that
organization capability. A personal access token is also narrowed by its live
organization and capability scopes.
Results use a deterministic newest-first order: occurredAtUtc descending,
then event id descending. Set limit from 1 through 200. When nextCursor
is present, pass it unchanged as after with the same filters:
GET /v1/orgs/{organizationId}/permission-audit?result=Denied&capabilityKey=DelegatePermissionManagement&limit=100
Authorization: Bearer {token}GET /v1/orgs/{organizationId}/permission-audit?result=Denied&capabilityKey=DelegatePermissionManagement&limit=100&after={nextCursor}
Authorization: Bearer {token}Filtering occurs after audit-read authorization and before page boundaries. Available filters cover:
fromUtcandtoUtcas inclusive UTC timestamps;actorSource(User,System,Migration, orExternalLink),actorUserId,actorCredentialKind,actorCredentialId, andpersonalAccessTokenId;targetTypeandtargetIdfor the recorded target entity or principal;capabilityKey,entitlementDefinitionId,entitlementDefinitionKey,entitlementVersionId, andpolicyDescriptorKey;scopeType,scopeId, and the ordinal case-sensitivedocumentPathfor the affected organization, cluster, location, or path resource;provenanceIdfor aSharedResourceAccessworkflow target;action,result,correlationId,permissionVersion, andpolicyVersion.
Each event reports actor and credential identity, target, capability/policy and
resource context, action/result/reason, correlation, safe before/after JSON,
and version markers when recorded. External-link events have no actorUserId;
their actorCredentialId is the exact link identity. Raw idempotency keys and internal disclosure
markers are not part of the response.
Audit events are retained indefinitely and cannot be updated or deleted through the application. Raw idempotency keys are stored only as SHA-256 values. Before and after payloads keep bounded operational identifiers, names, paths, values, counts, and outcomes while credential material, tokens, secrets, passwords, contact/network identifiers, and URLs are removed before persistence. Malformed or oversized payloads are replaced by an explicit redaction marker. Keep audit reasons free of secrets; denied attempts receive an additional stricter redaction and rate-limit policy.
Manage permission groups
Use /v1/orgs/{organizationId}/permission-groups for group lifecycle and the
/{groupId}/members subresource for enrollment:
GET /statereturns the current permission, policy, and authorization-state concurrency versions required before the first optimistic mutation.GETlists groups withoffsetandlimit.POSTcreates a group.GET /{groupId}reads one group.PUT /{groupId}renames it.POST /{groupId}/delete-previewreturns the member and assignment impact and every safely reportable validation issue.DELETE /{groupId}revalidates and deletes the complete group atomically.GET,PUT /{userId}, andDELETE /{userId}list, add, and remove group members.
Mutations require an idempotencyKey plus the current organization
authorization concurrency version. Rename and delete also require the current
group concurrency version; membership changes require the group's current
permission version. Refresh state after 409 Conflict instead of retrying with
stale versions.
Group lifecycle requires OrganizationGroupsManage; enrollment uses the
separate OrganizationGroupMembershipsManage capability. If the group contains
administrative assignments, the caller must already hold every resulting
administrative capability at an equal or broader scope. This rule applies when
the actor enrolls another user or themselves, so a self-enrollment cannot
manufacture administrative authority. Delegating permission-management
authority also requires DelegatePermissionManagement at the affected scope.
Deletion authority follows the complete impact, not only the group row. A
populated group also requires OrganizationGroupMembershipsManage, and the
caller must be allowed to remove every assignment contributed by the group.
The delete-preview response reports member/assignment counts and all safely
reportable missing authority. Commit repeats the preview against current group,
authorization, assignment, and membership versions and deletes nothing when
any part has changed.
Manage assignments
Use /v1/orgs/{organizationId}/permission-assignments to list, read, create,
update, reset, and delete assignments for User and Group principals.
Filtering supports principal type and ID, capability, scope type and ID, and an
ordinal case-sensitive document path.
Persisted assignment targets are limited to Organization, Cluster, and
Location. Bundle, document, and Job IDs are evaluation contexts, not ACL
targets. Document permissions use the matching organization, cluster, or
location Documents capability and may add a normalized path. Organization
Document paths address only the organization library; Cluster Document paths
may be organization defaults or cluster rules; Location Document paths may be
organization defaults, cluster defaults, or exact location rules. Paths are
anchored literal subtree prefixes, preserve case, and compare ordinally, so
/A matches /A and /A/B but not /AB or /a. Leading, trailing, repeated,
and backslash separators canonicalize to a slash-trimmed key. Empty/root-only,
. or .. traversal, and overlong paths are rejected before assignment
validation probes any resource. Glob and regular-expression syntax has no
special matching behavior; path prefixes are always literal.
Creating a path assignment atomically materializes any missing logical ancestor and managed-root folders in every currently applicable concrete library. Exact rules from multiple principals or origins reuse the same case-sensitive folder with independent bindings, so removing one rule cannot unlock a root still referenced by another. Folder creation is policy structure only and does not grant access beyond the assignment's final evaluated value. New organization-owned clusters and locations apply the relevant organization and cluster defaults in the same database transaction that creates the resource, so the library is never reported writable before its managed roots exist.
Folder list responses expose isPermissionManaged, isLocked, and lockReason.
An exact root referenced by one or more path assignments returns both flags as
true with lockReason: "permission_managed_path". Ancestors created only to
complete that path remain unlocked unless another assignment binds the ancestor
itself. Document-derived folders without an explicit folder record also return
both flags as false and no lock reason.
Ordinary folder rename, move, and delete endpoints reject a managed root with
HTTP 409 and code: "permission_managed_path"; change the corresponding
permission path instead. This lock protects the root structure, not its
contents: authorized document operations may still move files into, within, or
out of the managed subtree.
Rename, reconcile, and unlock managed paths
A permission-policy rename runs a case-sensitive collision and authority
preflight over every affected assignment and concrete document library before
changing state. Renaming /A can rewrite exact /A rules and path-segment
descendants such as /A/B only when the renamed folder and every affected rule
cover the same complete library set. It never rewrites a substring such as
/AB, never merges /A with case-distinct /a, and never silently splits a
partially overlapping rule. A surviving exact binding or unsafe broader/partial
coverage rejects the complete rename.
The commit updates assignment path literals, logical folders, file-artifact folder paths, bindings, audit state, permission versions, and outbox state as one policy mutation. Object-storage keys are unchanged. Work that must finish across multiple libraries records durable reconciliation state rather than reporting a partially repaired policy as complete. Reconciliation moves through pending/running and terminal succeeded or failed states; the background repair workflow is idempotent for propagation, rename, unlock, and interrupted work.
Removing the final assignment origin for a managed root removes its binding and
unlocks the existing folder, but never deletes the folder or its contents. If
another exact or overlapping binding still owns that root, the folder remains
locked. A later entitlement ceiling of Unavailable makes the assignment
dormant but does not remove its binding or unlock its policy structure.
Autocomplete document paths
Use GET /v1/orgs/{organizationId}/permission-document-paths/autocomplete
when a permission editor needs folder choices. Required query fields are
capabilityKey, scopeType, and scopeId; optional fields are parentPath,
the ordinal case-sensitive namePrefix, offset, and limit from 1 through
200.
The capability and scope choose the document libraries:
OrganizationDocumentswith the matchingOrganizationscope reads that organization's direct document library.ClusterDocumentswithClusterreads that exact cluster library. WithOrganization, it aggregates administrable cluster libraries.LocationDocumentswithLocationreads that exact location library. WithClusterorOrganization, it aggregates administrable location libraries beneath that scope.
Exact organization requests require ManageOrganizationPermissions; exact
cluster and location requests require ManageResourcePermissions. Aggregate
requests are bounded before any folder lookup to concrete libraries where the
caller has ManageResourcePermissions, so a manager confined to one cluster
does not discover another cluster's locations or folder names.
GET /v1/orgs/{organizationId}/permission-document-paths/autocomplete?capabilityKey=LocationDocuments&scopeType=Organization&scopeId={organizationId}&parentPath=/Cases&namePrefix=N&limit=100
Authorization: Bearer {token}Each item contains the canonical case-preserved fullPath, name,
hasChildren, isPermissionManaged, isLocked, lockReason, and coverage.
Use fullPath as the next parentPath to traverse one level. Full means the
path exists in every authorized library participating in that aggregate;
Partial means it exists in only part of that authorized set. The response
does not identify or count libraries, locations, files, or documents. Paths
are de-duplicated and sorted ordinally before pagination, so /A and /a
remain separate results. Invalid traversal and overlong paths are rejected
before authorization or folder-storage probes.
Call POST /v1/orgs/{organizationId}/permission-assignments/validate with a
mutation kind and candidate before committing. The non-mutating response uses
the same principal, resource, concurrency, delegation, and entitlement-ceiling
validators as the commit path. It reports the current/prospective canonical
value and bounded affected-principal/user counts.
Create and update accept a positive binary or tiered value. Reset requires
None. Delete omits value and removes only the manual origin. Every mutation
recomputes the canonical assignment from all active manual, invitation,
shared-workflow, and migration origins, so deleting a manual origin cannot
silently remove independent workflow access. Reads return raw canonical and
origin values plus the current ceiling, capped value, and dormant status.
New or increased manual grants above the active entitlement ceiling return
422 Unprocessable Entity with code
organization_entitlement_ceiling_exceeded. Reduction, reset, and deletion
remain available. Existing above-ceiling assignments stay stored and appear as
dormant configuration; a reviewed later entitlement transition can reactivate
them.
Manage protected owners
Use /v1/orgs/{organizationId}/owners to list protected owners. Owner changes
use POST /validate and POST with mutation kind Add, Transfer, or
Remove. They are available only to a current protected owner and cannot be
delegated through a group or ordinary assignment. An organization may have
multiple protected owners.
Owner changes require a recent interactive login. A refreshed session or a
personal access token does not satisfy this step-up check; sign in again and
submit the mutation within ten minutes. The API derives this result from the
authenticated session—there is no client-controlled stepUpVerified field.
The transaction always preserves at least one protected owner. Remove may
target only a different current owner; an owner cannot remove their own
relationship, even when another owner exists. Use Transfer when the acting
owner intends to establish a replacement and remove their own relationship in
one atomic transaction.
The organization roster returns isOwner independently of the legacy
membership role. Its actions object bounds whether the current caller may
present add-owner, remove-owner, or transfer controls for that specific row.
Use the roster response's top-level authorizationStateConcurrencyVersion for
the owner preview and apply requests; it remains available independently of
permission-group administration visibility.
Owner status may be displayed beside permission groups as a system chip, but
it is not a permission group and must use the protected-owner endpoints.
Ordinary member removal is unavailable for protected-owner rows.
Pending invitation rows use the same protected system chip. For a ghost row,
isOwner represents owner intent only: it grants no authority and does not
change the active owner count. A current owner with a recent interactive login
previews and applies the intent through
POST /v1/orgs/{organizationId}/owners/invitations/{invitationId}/validate
and POST /v1/orgs/{organizationId}/owners/invitations/{invitationId} with
isOwner, the row's invitation concurrency version, the roster's authorization
concurrency version, and one stable idempotency key. Ordinary group editing
preserves this intent. Successful bearer-link acceptance creates the membership
shell and protected owner relation atomically for the accepting active account;
failed acceptance creates neither.
Read organization policy and usage
GET /v1/orgs/{organizationId}/entitlements requires
OrganizationEntitlementsView. It returns the exact active definition/version,
activation or expiry, effective capability ceilings, and typed operational
limits. This route is read-only and cannot attach policy to a user or group.
GET /v1/orgs/{organizationId}/usage independently requires
OrganizationUsageView. It returns effective Document and Bundle storage
limits and sources, durable and actively reserved bytes, remaining capacity,
organization-wide current and actively reserved Cluster and Location counts,
current UTC-month Job use, and non-resetting lifetime Job use. Only
monthlyJobs contains periodStartUtc and resetAtUtc; the Cluster, Location,
and lifetime ledgers never reset. Ordinary
membership does not disclose these details, and neither read capability permits
capacity or usage mutation.
Finite Cluster, Location, monthly Job, and lifetime Job limits are part of each published entitlement version, including custom tiers. Lowering a current-count limit below existing usage blocks only additional creates or admissions. It does not remove existing Clusters, Locations, or Jobs, and it does not revoke otherwise-authorized reads, updates, or deletions. A new logical Job admission charges its UTC-month and lifetime ledgers atomically; retries of the same idempotent admission do not consume either allowance twice.
Platform entitlement-definition, version, organization-transition, default,
capacity, and reconciliation operations are separate AdminFull workflows and
are not assignable organization capabilities.
The organization entitlement-pin administration surface uses one lifecycle for
exact version changes, suspension, resume, explicit activation, and expiry
changes. Call POST /v1/admin/orgs/{organizationId}/entitlement-pin/validate
with the intended lifecycle kind, exact source pin and policy versions, target
state, and UTC effective time before creating the transition. Only one pending
transition may exist; a new command can explicitly replace it, and its durable
status remains readable at
GET /v1/admin/orgs/{organizationId}/entitlement-pin/transitions/{transitionId}.
Immediate and scheduled execution both use the same stale-source protection.
The validation response also reports operationalUsageImpacts for storage,
Cluster count, Location count, UTC-month Jobs, and lifetime Jobs against the
target version. Every item includes target limit, used/reserved values,
remaining allowance, and overage; only the UTC-month Job item has
resetAtUtc.
Retired targets cannot be newly selected, scheduled, resumed, reactivated, or
extended. An existing active retired pin may remain active until its current
expiry and may be shortened immediately. Access expires exactly at
validUntilUtc; authorization does not wait for a scheduler, transition write,
or notification delivery. A background detector later records exactly one
system-source expiry audit event and a correlated policy-cache invalidation for
that expiry boundary. Delayed or retried event delivery cannot extend access.
Organization Membership and Invitations
The workflow for joining organizations, accepting invitations, and managing membership-aware app state.
Organization Activation and Billing
Activate a new organization through Stripe Checkout, inspect webhook-derived subscription status, and understand manually managed enterprise organizations.