> ## 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.

# Team Management: Invites, Members, and Custom Roles

> Invite teammates by email and assign roles, accept organization invitations by token, and create custom roles with fine-grained permission sets.

Nyota Imara lets you build a team around your organization with role-based access control. You can invite teammates by email, assign them a built-in role, and create custom roles with the exact permissions your workflows require.

## Built-in roles

Every organization comes with four built-in roles:

| Role      | Typical use                                                  |
| --------- | ------------------------------------------------------------ |
| `owner`   | Full control — billing, team, settings, and all features     |
| `admin`   | Manage team and settings, but not billing                    |
| `billing` | Manage payments and subscriptions only                       |
| `member`  | Operational access to commerce, logistics, and notifications |

***

## Invite a team member

Send a `POST` request to `/v1/organizations/:id/invites`. The invitee receives an email with a secure, 7-day link to join.

```bash theme={null}
curl -X POST https://api.nyotaimara.com/v1/organizations/org_01j9kxp8a3bvc0nqrtzwmde4fy/invites \
  -H "Authorization: Bearer <your_token>" \
  -H "X-Organization-Id: org_01j9kxp8a3bvc0nqrtzwmde4fy" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "amara.odhiambo@savanasupplies.co.ke",
    "roleName": "admin"
  }'
```

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Invitation sent to amara.odhiambo@savanasupplies.co.ke."
}
```

<Note>
  If the email address already belongs to a member of the organization, the server returns `409 Conflict`. Re-sending to a pending invitee replaces the previous invite.
</Note>

***

## Accept an invitation

The invitee clicks the link in their email and signs in at `https://accounts.nyotaimara.com/invites/accept`. Once authenticated, the invitation is accepted by calling:

```bash theme={null}
curl -X POST https://api.nyotaimara.com/v1/organizations/invites/accept \
  -H "Authorization: Bearer <invitee_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "a3f8e2c1d9b047fe..."
  }'
```

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Successfully joined the organization!"
}
```

<Info>
  The accept endpoint is a personal context route — it does **not** require the `X-Organization-Id` header. The invite token carries the organization and role information.
</Info>

***

## List members and pending invites

Retrieve all active members and unaccepted invitations in one call:

```bash theme={null}
curl https://api.nyotaimara.com/v1/organizations/org_01j9kxp8a3bvc0nqrtzwmde4fy/members \
  -H "Authorization: Bearer <your_token>" \
  -H "X-Organization-Id: org_01j9kxp8a3bvc0nqrtzwmde4fy"
```

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "members": [
      {
        "id": "usr_01jb2kqp8a3bvc0nqrtzwmde9xy",
        "name": "Amara",
        "email": "amara.odhiambo@savanasupplies.co.ke",
        "avatarUrl": "https://cdn.nyotaimara.com/avatars/amara.jpg",
        "role": "admin",
        "joinedAt": "2025-11-05T07:14:00.000Z"
      }
    ],
    "invites": [
      {
        "id": "inv_01jb3nrm4p7xyz",
        "email": "brian.kamau@savanasupplies.co.ke",
        "role": "member",
        "expiresAt": "2025-11-12T07:14:00.000Z"
      }
    ]
  }
}
```

***

## Custom roles

If the four built-in roles do not match your access requirements, create a custom role with a specific set of permission IDs.

### Create a custom role

```bash theme={null}
curl -X POST https://api.nyotaimara.com/v1/organizations/iam/roles \
  -H "Authorization: Bearer <your_token>" \
  -H "X-Organization-Id: org_01j9kxp8a3bvc0nqrtzwmde4fy" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Logistics Manager",
    "description": "Can create delivery estimates and view orders, but cannot access billing.",
    "permissionIds": [
      "perm_logistics_delivery_read",
      "perm_oms_order_read"
    ]
  }'
```

### Update a custom role's permissions

```bash theme={null}
curl -X PATCH https://api.nyotaimara.com/v1/organizations/iam/roles/role_01jb9xyz \
  -H "Authorization: Bearer <your_token>" \
  -H "X-Organization-Id: org_01j9kxp8a3bvc0nqrtzwmde4fy" \
  -H "Content-Type: application/json" \
  -d '{
    "permissionIds": [
      "perm_logistics_delivery_read",
      "perm_oms_order_read",
      "perm_oms_order_create"
    ]
  }'
```

### Delete a custom role

```bash theme={null}
curl -X DELETE https://api.nyotaimara.com/v1/organizations/iam/roles/role_01jb9xyz \
  -H "Authorization: Bearer <your_token>" \
  -H "X-Organization-Id: org_01j9kxp8a3bvc0nqrtzwmde4fy"
```

<Warning>
  Deleting a role does not automatically remove it from members who hold it. Reassign affected members before deleting a role to avoid access inconsistencies.
</Warning>

### View available roles and permissions

To see all current roles and the full list of available permission IDs for your organization:

```bash theme={null}
curl https://api.nyotaimara.com/v1/organizations/iam/roles \
  -H "Authorization: Bearer <your_token>" \
  -H "X-Organization-Id: org_01j9kxp8a3bvc0nqrtzwmde4fy"
```

***

## Endpoint reference

| Method   | Endpoint                              | Required policy                |
| -------- | ------------------------------------- | ------------------------------ |
| `POST`   | `/v1/organizations/:id/invites`       | `org:member:invite`            |
| `POST`   | `/v1/organizations/invites/accept`    | Authenticated (no org context) |
| `GET`    | `/v1/organizations/:id/members`       | `org:member:read`              |
| `GET`    | `/v1/organizations/iam/roles`         | `org:organization:read`        |
| `POST`   | `/v1/organizations/iam/roles`         | `org:organization:update`      |
| `PATCH`  | `/v1/organizations/iam/roles/:roleId` | `org:organization:update`      |
| `DELETE` | `/v1/organizations/iam/roles/:roleId` | `org:organization:update`      |
