Roles and permissions
Decide what each person can do in your application, across your whole project or inside each company, and ask Mailmus before acting.
Your server asks one question before it acts: can this person do this? Mailmus answers with a yes or a no, and says why.
It works the same whether you sign people in with Mailmus Auth or on your own, and whether or not you use organizations.
How it fits together
- A permission is something a person can do in your application, written
resource:action, for exampleinvoice:create. - A role groups permissions. It has a scope:
- a project role is given to a person, for your whole application (
support,analyst); - an organization role is given to a member, inside one company (
billing).
- a project role is given to a person, for your whole application (
- A person can have several roles. Their access is everything their roles allow together.
A project role never gives access inside an organization, unless you mark it as applying to all organizations. That is how your own support team can help every company without being added to each one.
Declare your permissions and roles
const api = `https://api.mailmus.app/projects/${projectId}`;
const headers = { Authorization: `Bearer ${secretKey}`, "Content-Type": "application/json" };
await fetch(`${api}/access/permissions`, {
method: "POST",
headers,
body: JSON.stringify({ key: "invoice:create" }),
});
await fetch(`${api}/access/roles`, {
method: "POST",
headers,
body: JSON.stringify({
key: "billing",
name: "Billing",
scope: "ORGANIZATION",
permissions: ["invoice:create"],
}),
});A role that is still given to someone cannot be deleted: remove it from those people first, so that nobody loses access without their session knowing.
Give roles
To a person, for your whole project:
// PUT /projects/{projectId}/customers/{id}/roles
// { "roles": ["support"] }To a member of an organization:
// POST /projects/{projectId}/b2b/organizations/{id}/members
// { "externalUserId": "user_8291", "roles": ["org:admin", "billing"] }
// PATCH /projects/{projectId}/b2b/organizations/{id}/members/{membershipId}
// { "roles": ["org:member"] }Changing someone's roles signs out their current Mailmus sessions, so their next token reflects the change.
Check access
const res = await fetch(`${api}/access/check`, {
method: "POST",
headers,
body: JSON.stringify({
externalUserId: "user_8291",
organizationExternalId: "cus_acme",
permission: "invoice:create",
}),
});
const { allowed, reason, roles } = await res.json();Identify the person with customerId or with your own externalUserId. Leave out the organization to ask about your whole project.
A refusal is a normal answer, not an error: allowed is false and reason tells you why. Add "explain": true to get each step of the decision.
To answer "why can't Sophie refund this invoice?" without writing code, open Check access in Auth → Roles & permissions or B2B → Access, or use Explain on a Customer or on an organization member. The dashboard asks the same question your server does and shows each step of the answer.
reason | Meaning |
|---|---|
PROJECT_ROLE | Allowed by one of the person's project roles. |
ORGANIZATION_ROLE | Allowed by one of the member's roles in this organization. |
PROJECT_ROLE_ALL_ORGANIZATIONS | Allowed by a project role that applies to all organizations. |
NO_ROLE_GRANTS | None of the roles considered includes this permission. |
UNKNOWN_PERMISSION | This permission was never declared in the project. |
CUSTOMER_NOT_FOUND | Nobody with this ID in the project. |
NOT_A_MEMBER | The person does not belong to this organization. |
MEMBERSHIP_SUSPENDED | The person's membership in this organization is suspended. |
ORGANIZATION_NOT_FOUND | No organization with this ID in the project. |
ORGANIZATION_SUSPENDED | The organization is suspended. |
ORGANIZATIONS_DISABLED | Organizations are turned off for this project. |
Built-in organization roles
Every project that uses organizations has three roles you cannot delete:
| Role | Can |
|---|---|
org:owner | Everything below, and transfer ownership. |
org:admin | Invite people, remove members, change members' roles. |
org:member | Nothing by default. |
You can add your own permissions to them. The permissions that start with mailmus: belong to Mailmus and stay on these roles. Role keys that start with org: are reserved for them.
An organization always keeps at least one org:owner.
In the session token
If you sign people in with Mailmus Auth, the token carries roles (the person's project roles) and, when an organization is active, orgId and orgRoles (their roles in that organization, such as ["org:admin", "billing"]). orgRole (OWNER, ADMIN or MEMBER) is still there for existing integrations; prefer orgRoles. They are a snapshot taken when the token was issued: to decide on something that matters, use the access check.
Next
- Organizations
- Verify sessions
- Webhooks:
access_role.*,access_permission.*andcustomer.roles_updated.