# 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 must have 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 (e.g., "Admin", "Moderator", "Viewer")
* **Permission**: A specific action like "create conversation" or "view user data"
* **Conditions**: Rules that limit when permissions apply (e.g., "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}` 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 if 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 don't 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/edit roles that have equal or fewer privileges than yours

## Common Role Examples

### Content Moderator

A role that can review admin-visible conversations/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 complex 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.
