# Role-Based Permissions

This guide shows you how to manage user permissions in your organization using Amigo's role management APIs.

## What You'll Learn

* How to create and manage roles for different user types
* How to control what actions users can perform
* How to assign roles to users
* Common permission patterns and best practices

## Getting Started

Every user in your organization has exactly one role. Roles define what actions users can perform, such as creating conversations, viewing data, or managing other users.

### Basic concepts

* **Role**: a set of permissions you assign to users (for example "Admin", "Moderator", "Viewer").
* **Permission**: a specific action like "create conversation" or "view user data".
* **Conditions**: rules that limit when permissions apply (for example "only in your organization").

## Working with Role APIs

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/role/" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/role/" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/role/{role\_name}" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/role/{role\_name}/assign" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Creating Permission Rules

When creating roles, you define permission grants that specify what users can do. Each grant has three parts:

```json
{
    "action": "Allow",
    "permission_name": "Conversation:CreateConversation",
    "conditions": {
        "org_id": {
            "type": "Equals",
            "value": "{self_org_id}"
        }
    },
    "description": "Allow creating conversations in user's organization"
}
```

### Permission names

Permissions use a simple `Category:Action` format.

* `Conversation:CreateConversation`: create new conversations.
* `Conversation:GetConversation`: view existing conversations.
* `User:GetUserInfo`: view user information.

### Adding conditions

Conditions let you limit when permissions apply. For example, you might want users to only access data in their own organization:

```json
{
    "conditions": {
        "org_id": {
            "type": "Equals",
            "value": "{self_org_id}"
        }
    }
}
```

The `{self_org_id}` placeholder automatically becomes the user's organization when the permission is checked.

### Condition types

You can use these condition types to control when permissions apply.

| Type        | When to Use                                | Example                                                        |
| ----------- | ------------------------------------------ | -------------------------------------------------------------- |
| `Equals`    | Grant permission for a specific value      | `{"type": "Equals", "value": "premium_service"}`               |
| `NotEquals` | Block permission for a specific value      | `{"type": "NotEquals", "value": "restricted_service"}`         |
| `In`        | Allow permission for any of several values | `{"type": "In", "values": ["basic", "premium", "enterprise"]}` |

{% hint style="info" %}
**Variable substitution**

* `{self_org_id}`: the authenticated user's organization ID.
* `{self}`: the authenticated user's user ID (useful for user- or conversation-owner checks).
* `{self_role_name}`: the authenticated user's role name (used by some role-related permissions).
  {% endhint %}

## Understanding Permission Behavior

### How permissions are checked

{% @mermaid/diagram content="%%{init: {"theme": "base", "themeVariables": {"actorBkg": "#083241", "actorTextColor": "#FFFFFF", "actorBorder": "#083241", "signalColor": "#575452", "signalTextColor": "#100F0F", "labelBoxBkgColor": "#F1EAE7", "labelBoxBorderColor": "#D7D2D0", "labelTextColor": "#100F0F", "loopTextColor": "#100F0F", "noteBkgColor": "#F1EAE7", "noteBorderColor": "#D7D2D0", "noteTextColor": "#100F0F", "activationBkgColor": "#E8E2EB", "activationBorderColor": "#083241", "altSectionBkgColor": "#F1EAE7", "altSectionColor": "#100F0F"}}}%%
sequenceDiagram
autonumber
participant U as User / Client
participant API as Amigo API
participant P as Permission Engine

U->>API: Call endpoint (e.g., create conversation)
API->>P: Evaluate for<br/>{ user\_id, role\_name, request }
P-->>P: Load role and permission grants
P-->>P: Resolve conditions<br/>(e.g., {self\_org\_id})
alt Any deny matches
P-->>API: Denied (deny > allow)
API-->>U: 403 Forbidden<br/>{ missing\_permission }
else Allow matches and no denies
P-->>API: Allowed
API-->>U: Perform action / return data
end" %}

When a user tries to perform an action, the system:

1. Looks at all permission grants in the user's role.
2. Finds grants that match the action being attempted.
3. Checks whether any conditions are met.
4. **Deny grants always win**. If any deny grant matches, the action is blocked.
5. If no deny grants match but an allow grant does, the action is permitted.

{% hint style="success" %}
**Key rule:** deny permissions always take precedence over allow permissions.
{% endhint %}

### What happens when permissions are missing

Different API endpoints handle missing permissions in different ways.

**Some endpoints return errors:**

```json
{
    "error": "Forbidden",
    "message": "Missing required permission: Conversation:CreateConversation"
}
```

**Others filter results silently:**

* `GetConversations` only returns conversations you can access.
* `GetUsers` only shows users you have permission to view.

**Some hide specific fields:**

* If you do not have message-level access, `final_message` may be empty in `GetConversations`.
* If you lack service-version access, `version_set_info` may be omitted in `GetConversations`.
* This prevents errors while protecting sensitive information.

### Role hierarchy requirements

When managing other users' roles, you need sufficient privileges.

{% @mermaid/diagram content="%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#D4E2E7", "primaryTextColor": "#100F0F", "primaryBorderColor": "#083241", "lineColor": "#575452", "textColor": "#100F0F", "clusterBkg": "#F1EAE7", "clusterBorder": "#D7D2D0"}}}%%
flowchart TB
A(\[You]) --> B{Target role privilege<br/>> your role?}
B -- Yes --> D\[Denied<br/>Insufficient privilege]
B -- No --> C\[Allowed<br/>Proceed]
style D fill:#F0DDD9,stroke:#AA412A,color:#100F0F
style C fill:#DDE3DB,stroke:#2c3827,color:#100F0F" %}

* **Inviting users**: you can only assign roles with equal or fewer privileges than your own.
* **Creating API keys**: API keys can only have roles with equal or fewer privileges than yours.
* **Modifying roles**: you can only create or edit roles that have equal or fewer privileges than yours.

## Common Role Examples

### Content moderator

A role that can review admin-visible conversations and messages but cannot interact in them:

```json
{
  "role_name": "content_moderator",
  "description": "Can review admin-visible conversations in their organization",
  "is_base_role": false,
  "frontend_view": "admin",
  "permission_grants": [
    {
      "action": "Allow",
      "permission_name": "Conversation:GetConversation",
      "conditions": {
        "org_id": {"type": "Equals", "value": "{self_org_id}"},
        "conversation_visible_to_admin": {"type": "Equals", "value": true}
      },
      "description": "View admin-visible conversations in own organization"
    },
    {
      "action": "Allow",
      "permission_name": "Conversation:GetMessage",
      "conditions": {
        "org_id": {"type": "Equals", "value": "{self_org_id}"},
        "conversation_visible_to_admin": {"type": "Equals", "value": true}
      },
      "description": "Read messages in admin-visible conversations"
    },
    {
      "action": "Deny",
      "permission_name": "Conversation:InteractWithConversation",
      "conditions": {},
      "description": "Cannot interact in conversations"
    }
  ]
}
```

### Read-only user

A role that can only view their own conversations, never create or interact:

```json
{
  "role_name": "viewer",
  "description": "Can only view own conversations",
  "is_base_role": false,
  "frontend_view": "client",
  "permission_grants": [
    {
      "action": "Allow",
      "permission_name": "Conversation:GetConversation",
      "conditions": {
        "org_id": {"type": "Equals", "value": "{self_org_id}"},
        "conversation_user_id": {"type": "Equals", "value": "{self}"}
      },
      "description": "View only the authenticated user's conversations"
    },
    {
      "action": "Deny",
      "permission_name": "Conversation:CreateConversation",
      "conditions": {},
      "description": "Cannot create new conversations"
    },
    {
      "action": "Deny",
      "permission_name": "Conversation:InteractWithConversation",
      "conditions": {},
      "description": "Cannot interact in conversations"
    }
  ]
}
```

## Best Practices

### Start simple

Begin with basic roles like "Admin", "User", and "Viewer" before creating more intricate permission structures.

### Use organization scoping

Almost all permissions should include `"org_id": {"type": "Equals", "value": "{self_org_id}"}` to keep users within their organization.

### Prefer allow over deny

Design roles with specific allow permissions rather than broad permissions with deny exceptions.

### Test permission changes

Always test role modifications in a development environment before applying them to production users.

### Document your roles

Use clear role names and descriptions so other developers understand their purpose.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.amigo.ai/developer-guide/classic-api/permissions/role-based-permissions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
