---
title: "Creates a custom role, like Roles → Create Role in the app."
method: POST
path: "/api/v1/roles"
tags: ["Roles"]
---

# Creates a custom role, like Roles → Create Role in the app.

`POST /api/v1/roles`

## Request

- Base URL: `https://app.flexonthejob.com`
- URL: `https://app.flexonthejob.com/api/v1/roles`
- Auth: HTTP bearer

Requires `ManageRoles` and an `Idempotency-Key`. The name must be unique in the
organization (case-insensitive) and not a built-in role name; every permission must be a
FlexPermissions name held by both the API key and its creator. Assign it to accounts with
`customRoleId` / `customRoleIds` on `/api/v1/users`. Example:
`{ "name": "Dispatcher", "description": "Schedules crews", "permissions": ["ViewJobs", "ManageJobs"] }`.

## Request body

- CustomRoleWriteApiRequest: Body of `POST /api/v1/roles` (`name` required) and `PATCH /api/v1/roles/{id}` (only the fields sent change; `permissions` replaces the whole set). Example: `{ "name": "Dispatcher", "description": "Schedules crews", "permissions": ["ViewJobs", "ManageJobs"] }`.
  - `name` string, nullable: Role name, 1..50 characters, unique in the organization and not a built-in role name. Example: `"Dispatcher"`.
  - `description` string, nullable: Free-text description, up to 200 characters.
  - `permissions` string[], nullable: FlexPermissions names the role grants (see `get_org_capabilities` / the permission catalog). Each must be held both by the API key and by the key's creator. Example: `["ViewJobs", "ManageJobs"]`.

## Response `201`

Created; `Location` points at the new role.

- RoleDto: A role accounts can hold, as returned by `/api/v1/roles`: the built-in `OrganizationAdmin`, `Manager` and `User` (never `SystemAdmin`), then the organization's custom roles.
  - `id` integer, nullable: Custom role id (use it as `customRoleId` / in `customRoleIds` on the user endpoints); null for a built-in role. Example: `4`.
  - `name` string: Role name; for a built-in role this is the value to send as `role`. Example: `"Manager"`.
  - `description` string: What the role is for. Example: `"Manager with inventory and location management access"`.
  - `isBuiltIn` boolean: True for OrganizationAdmin / Manager / User, which cannot be edited.
  - `rank` integer: Hierarchy rank: OrganizationAdmin 3, Manager 2, User 1; custom roles 0 (they add permissions, not rank).
  - `permissions` string[]: Permissions the role grants, as FlexPermissions names. Example: `["ViewInventory", "ManageJobs"]`.
  - `createdAt` string, date-time, nullable: UTC creation time (ISO-8601); null for built-in roles.
  - `updatedAt` string, date-time, nullable: UTC last modification time (ISO-8601); null for built-in roles.

## Other responses

- `400`: Malformed body or missing `Idempotency-Key`.
- `401`: Unauthorized
- `403`: A permission is not held by the key or its creator (listed in `errors`).
- `409`: A role with this name already exists, or the key's creator is unknown on this server.
- `422`: A field is unacceptable (blank or long name, unknown permission); listed in `errors`.
- `429`: Too Many Requests

---

[API](https://skmtc.dev/flexonthejob/apis/flex-api.md) · [All operations](https://skmtc.dev/flexonthejob/apis/flex-api/llms.txt) · [OpenAPI document](https://skmtc.dev/flexonthejob/apis/flex-api/revisions/19c8f4d27acf?raw)
