> ## Documentation Index
> Fetch the complete documentation index at: https://handbook.nyotaimara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Permissions and Roles: How PBAC Works on Nyota Imara

> Learn how Nyota Imara enforces permissions using PBAC policies in namespace:resource:action format, built-in org roles, and custom role creation.

Nyota Imara uses **Policy-Based Access Control (PBAC)** to decide what each user or organization member can do. Every protected action maps to a policy string in the format `namespace:resource:action`. When you make a request, the platform evaluates your current permission set against the required policy and either allows or denies the operation.

## Policy string format

Every permission is a three-part string separated by colons:

```
namespace:resource:action
```

| Part        | Description                        | Examples                                                 |
| ----------- | ---------------------------------- | -------------------------------------------------------- |
| `namespace` | The service or domain boundary     | `org`, `identity`, `billing`, `oms`                      |
| `resource`  | The specific entity being acted on | `member`, `user`, `payment`, `order`                     |
| `action`    | The operation being performed      | `read`, `create`, `update`, `delete`, `invite`, `submit` |

A request missing the required policy receives a `403 Forbidden` response with the exact policy string that was evaluated:

```json theme={null}
{
  "success": false,
  "error": "Forbidden: You lack the required IAM policy (org:member:invite) to perform this request."
}
```

## Key permissions

The table below covers the permission strings you are most likely to encounter when building on Nyota Imara.

| Permission                | What it unlocks                                                     |
| ------------------------- | ------------------------------------------------------------------- |
| `org:organization:read`   | View organization details and IAM role configuration                |
| `org:organization:update` | Update organization settings; create, edit, and delete custom roles |
| `org:member:read`         | List active members and pending invitations                         |
| `org:member:invite`       | Send invitations to new team members                                |
| `org:kyb:read`            | View KYB documents and verification status                          |
| `org:kyb:submit`          | Submit KYB documents for review                                     |
| `identity:user:read`      | Read user profile and KYC status                                    |
| `billing:payment:create`  | Initiate payments and add payment methods                           |
| `oms:order:create`        | Create new orders in the commerce system                            |
| `platform:org:create`     | Create a new organization (personal context)                        |

## Built-in organization roles

Every organization ships with four protected built-in roles. You cannot modify or delete them.

| Role        | Included permissions                                                                                                         |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **owner**   | All permissions across every namespace — equivalent to super-access within the organization.                                 |
| **admin**   | `org:organization:read`, `org:organization:update`, `org:member:read`, `org:member:invite`, `org:kyb:read`, `org:kyb:submit` |
| **billing** | `billing:payment:create` and all billing-namespace read and write permissions. No org management or member access.           |
| **member**  | `org:organization:read`, `org:member:read` — basic read access to shared organization data.                                  |

<Note>
  The `owner` role is assigned automatically to the person who creates the organization and cannot be transferred through the API. To hand off ownership, contact Nyota Imara support.
</Note>

## Organization context and permissions

Your active permission set depends on which context you are operating in. When you send the `X-Organization-Id` header, Nyota Imara loads the permissions attached to your role in that specific organization. Without the header, only your personal (platform-level) permissions apply.

```bash theme={null}
# Without X-Organization-Id — personal permissions apply
GET /v1/organizations

# With X-Organization-Id — org role permissions apply
GET /v1/organizations/org_01HXYZ/members
X-Organization-Id: org_01HXYZ
```

This means the same user can have different effective permissions in different organizations, depending on the role they hold in each one.

## Checking your permissions

To see the full list of roles and their mapped permissions available in your organization, call:

```bash theme={null}
GET /v1/organizations/iam/roles
Authorization: Bearer <token>
X-Organization-Id: <org-id>
```

The response returns each role with an `isProtected` flag and the list of permission IDs currently mapped to it:

```json theme={null}
{
  "success": true,
  "data": {
    "roles": [
      {
        "id": "role_01HABC",
        "name": "admin",
        "isProtected": true,
        "permissions": ["perm_01H...", "perm_02H..."]
      },
      {
        "id": "role_01HDEF",
        "name": "auditor",
        "isProtected": false,
        "permissions": ["perm_01H..."]
      }
    ],
    "permissions": [
      { "id": "perm_01H...", "name": "org:organization:read" }
    ]
  }
}
```

## Custom roles

Organization owners can create custom roles that combine any set of granular permissions. This lets you define roles like `auditor` (read-only access) or `dispatcher` (order creation only) without granting broader built-in role access.

<Steps>
  <Step title="List available permissions">
    Call `GET /v1/organizations/iam/roles` to get the full list of permission IDs your organization can assign.
  </Step>

  <Step title="Create the custom role">
    Post the role name and an array of permission IDs:

    ```json theme={null}
    POST /v1/organizations/iam/roles

    {
      "name": "auditor",
      "description": "Read-only access to org data and billing history",
      "permissionIds": ["perm_01H...", "perm_02H..."]
    }
    ```

    Role names are automatically lowercased and sanitized — only letters, digits, and underscores are kept.
  </Step>

  <Step title="Update or delete the role later">
    Update a custom role's permissions with `PATCH /v1/organizations/iam/roles/:roleId`. Remove a custom role entirely with `DELETE /v1/organizations/iam/roles/:roleId`.

    <Warning>
      Before deleting a custom role, reassign all members currently holding that role. Deleting a role that is still assigned to users will fail with a foreign key constraint error.
    </Warning>
  </Step>
</Steps>

<Info>
  Built-in roles (`owner`, `admin`, `billing`, `member`) are protected — the API blocks any attempt to modify or delete them. Custom roles are fully manageable by organization owners.
</Info>
