---
title: "Organizations"
description: "Model Organization, OrgUnit, project, and access approval boundaries."
locale: "en"
---

> Documentation Index
> Fetch the relevant documentation index at: https://xid.dev/en/llms.txt
> Use this file to discover all available pages before exploring further.

# Organizations

## Organization hierarchy

An Instance contains top-level Organizations. An Organization can contain one level of SubOrg; each organization remains a policy, membership, branding, RBAC, and isolation boundary.

An OrgUnit is a department or team inside one Organization. It never changes TenantContext, issuer, token claims, or the one-level SubOrg limit.

- OrgUnit trees support a maximum depth of eight.
- Each member can have one primary OrgUnit and additional placements.
- The nearest active manager in the OrgUnit ancestor chain is the first access-request approver candidate.

## Projects and access policy

Projects group applications and authorization roles. The per-project `access_policy` controls only same-organization users without an effective UserGrant; cross-organization ProjectGrant authorization is unaffected.

| Project policy | Same-organization behavior | Self-service path |
| --- | --- | --- |
| Open | Allowed without a UserGrant. | No access request is needed. |
| Restricted | Denied; an administrator grants access directly. | No self-service request is available. |
| Approval required | Denied until an AccessRequest is approved. | The user submits an access request. |

## Access request lifecycle

AccessRequest moves from `pending` to `approved`, `denied`, `cancelled`, or `expired`. Every outcome is terminal, and pending requests expire lazily after 14 days.

Approval creates a traceable UserGrant in the same transaction. The requester cannot approve their own request; resolution falls through from the OrgUnit manager to project and organization managers.

| Method | Path | Purpose | Required scope |
| --- | --- | --- | --- |
| `GET, POST` | `/auth/access-requests` | Create and list the current user's requests. | `session` |
| `POST` | `/auth/access-requests/:id/cancel` | Cancel the current user's pending request. | `session` |
| `GET` | `/auth/access-approvals` | List requests awaiting the current user's approval. | `session` |
| `POST` | `/auth/access-approvals/:id/{approve\|deny}` | Approve or deny a pending request assigned to the current user. | `session` |
| `GET` | `/v1/organizations/:orgId/access-requests` | List requests inside one organization. | `access-requests:read` |
| `GET` | `/v1/organizations/:orgId/units` | Read the organization unit tree. | `org-units:read` |
| `POST, PATCH, DELETE, PUT` | `/v1/organizations/:orgId/units/*` | Create, update, move, archive, and manage members of units. | `org-units:write` |

## Security boundaries

- Every OrgUnit and AccessRequest query is scoped by `tenant_id` and `org_id`. Cross-organization or cross-tenant identifiers return 404 without revealing existence.
- Membership and project access are separate: invitations join an Organization, while AccessRequest grants an existing active member access to one Project.
- SCIM provisions users and memberships but does not map directory groups to OrgUnits or Project roles in the current implementation.
- The Management API uses cursor pagination and shared API-key or organization-manager guards. It does not reuse end-user business routes.

Source: https://xid.dev/organizations/index.mdx
