Skip to content

Chat permissions

A Chat permission, called a capability in the API, answers one question: may this user perform this kind of operation? It never answers which users they may do it with. A tenant gives permissions to roles, separately for each application.

Chat enforces 18 permissions. The reference lists each with the routes it unlocks: Capabilities.

Area Permissions
Conversations conversations.create, conversations.read, conversations.update, conversations.delete
Groups groups.create (create groups, and add members to a group you own), groups.manage (manage any group)
Channels channels.create, channels.manage (manage any channel)
Messages messages.send, messages.read (also needed for reactions, read state and typing), messages.update (your own messages), messages.delete (moderation: delete and edit other members’ messages)
Users users.lookup (members Chat already knows), users.lookup.directory (the whole tenant directory at the Identity Server)
Attachments attachments.upload, attachments.download
Administration administration.read, administration.manage

Direct conversations need only conversations.create. Groups and channels also need groups.create or channels.create.

Chat defines no roles. System roles such as tenant_owner and tenant_admin, and your own such as coach and client, live in the Identity Server. Chat receives a user’s roles and maps them to permissions.

  • The tenant owner or an admin holding administration.manage maps roles to permissions in Chat Administration, under Roles and permissions. The mapping is stored at the Identity Server.
  • The mapping is per context. The tenant-wide mapping holds tenant-level permissions such as administration.*. Each tenant application has its own mapping, and nothing is inherited between them.
  • Inside an application you can map the tenant’s roles and that application’s own roles, such as coach.
  • <code dir="auto">tenant_owner</code> always holds every permission, in every context. It is shown locked and cannot be edited.
  • Every other role starts with none, tenant_admin included. The owner first grants tenant_admin what it should be able to do.
  • Platform roles never carry Chat permissions.

Being a member of a tenant does not imply Chat permissions either. A user whose roles have no grants cannot look up users, start conversations or create groups and channels.

Take a Fitness app. Coach Ana may message her clients John and Sarah, but not a random member. That is a business rule. Chat has no idea what a coach is, so it cannot enforce it.

What Chat does enforce is the kind of operation:

Rule Who enforces it
“Ana may send messages” Chat, with messages.send
“Ana may start a conversation” Chat, with conversations.create
“Ana’s clients are John and Sarah” Your backend, in your database

Granting a permission applies to every holder of the role. If you gave the coach role conversations.create, any coach could open a chat with any tenant member who can use the application. That is exactly what your backend’s rules exist to prevent.

Users do not need conversations.create or users.lookup to take part in a conversation someone else created. For a backend-driven integration, grant your roles only what they need inside existing conversations:

Role Chat permissions inside the Fitness application
coach conversations.read, messages.read, messages.send, messages.update
client conversations.read, messages.read, messages.send, messages.update

Leave out conversations.create, groups.create and users.lookup. Your backend creates the conversations with a machine token instead; see Machine scopes.

Each operation lists what it needs, for example sending a message:

Chat permission: messages.sendUser scope: chat:accessMachine scope (any of): chat:messages.send

A caller without the permission gets 403 missing_capability, and message names the permission. The permission is checked together with membership: holding messages.send does not let a user post to a conversation they are not in, which answers 403 not_conversation_member.

To show or hide controls, an app asks Chat what the signed-in user holds:

GET /api/v1/tenants/{tenant_id}/applications/{application_id}/me/capabilities

The response lists capabilities and the user’s roles for display. Chat enforces every permission on every call regardless of what the UI shows.