SEAM API uses a database-driven Role-Based Access Control (RBAC) model. Every authenticated user carries aDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/TheSerchCp/SEAM-API/llms.txt
Use this file to discover all available pages before exploring further.
roleId in their JWT payload. Before a protected controller runs, roles.middleware.js looks up whether that role has been granted permission to call the exact route being requested. If no matching permission is found, the request is rejected with a 403 Forbidden error — even if the token itself is valid.
How the permission model works
Permissions are stored in apermissions table. Each permission has a nameUri column that identifies the route it covers. Roles are stored in a roles table, and the many-to-many relationship between roles and permissions lives in permissionXRole.
When a request arrives, roles.middleware.js constructs a nameUri string from the HTTP method and the Express route pattern, then queries the database to see whether the user’s role has been granted that URI:
LOWER() on both sides, so nameUri values are case-insensitive. A route-root path (/) is treated as an empty string to avoid double slashes (e.g., /api/v1/users instead of /api/v1/users/).
The nameUri pattern format
The nameUri is always METHOD /api/v1/<module>[/:param]. It must match exactly what the middleware constructs at runtime — including the param placeholder (e.g., :id), not an actual ID value.
| Route | Constructed nameUri |
|---|---|
GET /api/v1/users | GET /api/v1/users |
GET /api/v1/users/:id | GET /api/v1/users/:id |
PUT /api/v1/users/:id | PUT /api/v1/users/:id |
DELETE /api/v1/users/:id | DELETE /api/v1/users/:id |
POST /api/v1/roles | POST /api/v1/roles |
PUT /api/v1/roles/:idRole | PUT /api/v1/roles/:idRole |
DELETE /api/v1/roles/:idRole | DELETE /api/v1/roles/:idRole |
POST /api/v1/permission/register | POST /api/v1/permission/register |
POST /api/v1/permission/assign | POST /api/v1/permission/assign |
DELETE /api/v1/permission/unassign | DELETE /api/v1/permission/unassign |
DELETE /api/v1/permission/:id | DELETE /api/v1/permission/:id |
POST /api/v1/sidebar | POST /api/v1/sidebar |
PUT /api/v1/sidebar/:idItem | PUT /api/v1/sidebar/:idItem |
DELETE /api/v1/sidebar/:idItem | DELETE /api/v1/sidebar/:idItem |
POST /api/v1/sidebar/:idItem/role/:idRole | POST /api/v1/sidebar/:idItem/role/:idRole |
Auth-only vs. auth + roles routes
Not every protected route requires a permission check. Some read-only or utility routes only validate the JWT — they skiproles.middleware.js entirely. All mutation routes (create, update, delete, assign) require both.
| Route | Middleware chain |
|---|---|
GET /api/v1/roles | auth only |
GET /api/v1/permission | auth only |
GET /api/v1/permission/getByRoleId | auth only |
GET /api/v1/permission/getByNameUri | auth only |
| All other protected routes | auth → roles |
Setting up permissions for a new role
Create the role
Call
POST /api/v1/roles with a roleName and optional description. Save the idRole returned in the response.Register each permission
For every route the new role should be allowed to call, register a permission record using Repeat this step for each route the role needs (
POST /api/v1/permission/register. The nameUri must match the pattern shown in the table above exactly.PUT /api/v1/users/:id, DELETE /api/v1/users/:id, etc.). Save the idPermission returned from each call.Assign permissions to the role
Link each permission to the role using Repeat this step for every permission you want to grant to the role.
POST /api/v1/permission/assign. Supply the roleId and the permissionId together.Removing a permission from a role
To revoke access without deleting the permission record, callDELETE /api/v1/permission/unassign with the same roleId and permissionId pair used when assigning:
Permission checks are always evaluated live against the database. There is no in-memory cache. Changes to
permissionXRole take effect on the very next request — no server restart is required.