Voltair Roles API
The Roles API from Voltair — 2 operation(s) for roles.
The Roles API from Voltair — 2 operation(s) for roles.
openapi: 3.0.3
info:
title: Voltair ApiKeys Roles API
version: 0.1.0
description: 'Infrastructure inspection platform API. All endpoints are scoped to the authenticated organization via Bearer JWT or API key.
All timestamp fields on this API (createdAt, updatedAt, scheduledFor, capturedAt, expiresAt, deletedAt, etc.) are Unix timestamps in milliseconds since the epoch (UTC). Both request and response bodies use this representation.'
servers:
- url: /
security:
- BearerAuth: []
- ApiKeyAuth: []
tags:
- name: Roles
paths:
/roles:
get:
tags:
- Roles
operationId: listRoles
summary: List roles
description: Returns roles for the caller's organization. By default only org-scoped roles are returned. Pass `include=cluster` to also include cluster-wide roles (those with `organizationId == null`, e.g. super-admin and other system-actor roles); these are not assignable from the org UI but downstream consumers like the auth-context role lookup and the events page need them to resolve cluster-wide role IDs.
parameters:
- name: include
in: query
schema:
type: string
enum:
- cluster
description: Set to `cluster` to additionally include cluster-wide roles (`organizationId == null`). Omit for org-scoped roles only.
- $ref: '#/components/parameters/LimitParam'
- $ref: '#/components/parameters/CursorParam'
responses:
'200':
description: Success
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
type: object
required:
- data
- meta
properties:
data:
type: array
items:
$ref: '#/components/schemas/Role'
meta:
$ref: '#/components/schemas/PaginationMeta'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalError'
post:
tags:
- Roles
operationId: createRole
summary: Create role
description: Creates a custom role. isSystem and canSwitchOrganizations are always set to false server-side.
parameters:
- $ref: '#/components/parameters/IdempotencyKeyHeader'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateRoleRequest'
responses:
'201':
description: Created
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
type: object
required:
- data
- transactionId
properties:
data:
$ref: '#/components/schemas/Role'
transactionId:
type: string
format: uuid
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalError'
/roles/{roleId}:
parameters:
- name: roleId
in: path
required: true
schema:
type: string
format: uuid
get:
tags:
- Roles
operationId: getRole
summary: Get role
responses:
'200':
description: Success
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
type: object
required:
- data
properties:
data:
$ref: '#/components/schemas/Role'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalError'
put:
tags:
- Roles
operationId: updateRole
summary: Update role
description: Updates a custom role. Returns 403 if the role is a system role. Cannot edit id, isSystem, or canSwitchOrganizations.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateRoleRequest'
responses:
'200':
description: Success
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
type: object
required:
- data
- transactionId
properties:
data:
$ref: '#/components/schemas/Role'
transactionId:
type: string
format: uuid
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalError'
delete:
tags:
- Roles
operationId: deleteRole
summary: Delete role
description: Soft-deletes a custom role. Returns 403 if the role is a system role. Returns 409 if any active actors are currently assigned this role.
responses:
'200':
description: Success
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
type: object
required:
- data
- transactionId
properties:
data:
$ref: '#/components/schemas/Role'
transactionId:
type: string
format: uuid
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalError'
components:
schemas:
PaginationMeta:
type: object
required:
- cursor
properties:
cursor:
type: string
nullable: true
description: Opaque cursor for the next page; null when no more results
total:
type: integer
description: Total matching results across all pages; included when cheaply computable
Permission:
type: object
required:
- resource
- level
properties:
resource:
$ref: '#/components/schemas/PermissionResource'
level:
$ref: '#/components/schemas/PermissionLevel'
Role:
type: object
required:
- id
- name
- description
- permissions
- isSystem
- canSwitchOrganizations
- deletedAt
- createdAt
- updatedAt
properties:
id:
type: string
format: uuid
organizationId:
type: string
format: uuid
nullable: true
description: NULL for global roles (e.g. super-admin)
slug:
type: string
nullable: true
description: Stable identifier for the super-admin role
name:
type: string
description:
type: string
permissions:
type: array
items:
$ref: '#/components/schemas/Permission'
isSystem:
type: boolean
canSwitchOrganizations:
type: boolean
deletedAt:
type: number
nullable: true
createdAt:
type: number
updatedAt:
type: number
PermissionLevel:
type: string
enum:
- none
- read
- write
CreateRoleRequest:
type: object
required:
- name
- permissions
properties:
name:
type: string
description:
type: string
permissions:
type: array
items:
$ref: '#/components/schemas/Permission'
ErrorResponse:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable description
details:
type: object
additionalProperties: true
description: Optional structured info (e.g. field-level validation errors, conflictingEventIds)
UpdateRoleRequest:
type: object
properties:
name:
type: string
description:
type: string
permissions:
type: array
items:
$ref: '#/components/schemas/Permission'
PermissionResource:
type: string
enum:
- sites
- missions
- media
- organization
- users
- roles
- billing
- developer
- events
- transactions
responses:
BadRequest:
description: Bad request or validation error
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
TooManyRequests:
description: Rate limit exceeded
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
X-RateLimit-Limit:
schema:
type: integer
description: Maximum requests per window
X-RateLimit-Remaining:
schema:
type: integer
description: Requests remaining in current window
X-RateLimit-Reset:
schema:
type: number
description: Unix timestamp (ms) when the window resets
Retry-After:
schema:
type: integer
description: Seconds until the next rate limit window
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
NotFound:
description: Resource not found
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Forbidden:
description: Insufficient permissions
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Conflict:
description: Conflict (duplicate resource, in-use resource, or undo conflict)
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
InternalError:
description: Internal server error
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Unauthorized:
description: Authentication required
headers:
X-Request-Id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
parameters:
CursorParam:
name: cursor
in: query
schema:
type: string
description: Opaque pagination cursor from a previous response
IdempotencyKeyHeader:
name: Idempotency-Key
in: header
required: false
schema:
type: string
format: uuid
description: Idempotency key for POST requests. If a transaction with the same key already exists for the org, the server returns the original response without re-executing. Keys are valid for 48 hours.
LimitParam:
name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 200
description: Page size (default 50, max 200)
headers:
XRequestId:
description: Unique request identifier (UUID)
schema:
type: string
format: uuid
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: Cognito JWT access token
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: Organization-scoped API key