Files
query-orchestration/serviceAPIs/queryAPI.yaml
T
Jay Brown 2b43799f56 Merged in feature/admin-api (pull request #191)
admin api and associated tools

* in progress

admin api started and permit.io setup tool started

* docs

* build fix

* integration tests passing

* new permit variables

* fix permit

* fix delete regex

* fix delete response

* docs

* docs
2025-10-23 22:57:15 +00:00

2388 lines
68 KiB
YAML

---
openapi: 3.0.3
info:
title: Query Orchestration API
description: API documentation for the Query Orchestration services.
version: 0.0.1
contact:
email: piragavarapu@aarete.com
name: Aarete Inc.
url: https://aarete.com
license:
name: Aarete Inc.internal use
url: https://aarete.com
servers:
- url: https://doczy.com/v1
description: Production server
tags:
- name: ClientService
description: Operations related to clients
- name: CollectorService
description: Operations related to collectors
- name: DocumentsService
description: Operations related to documents
- name: QueryService
description: Operations related to queries
- name: ExportService
description: Operations related to exports
- name: AuthService
description: Operations related to authentication
- name: AdminService
description: Operations related to user management and administration
paths:
/client:
post:
operationId: createClient
tags:
- ClientService
summary: Create a new client
description: Creates a new client with the provided details.
security:
- jwtAuth: []
requestBody:
description: The details required to create a client
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ClientCreate"
responses:
"201":
description: Client created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ClientIDBody"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: getClient
tags:
- ClientService
summary: Get a client by ID
description: Retrieves a specific client by its ID.
security:
- jwtAuth: []
responses:
"200":
description: Client details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DocClient"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateClient
tags:
- ClientService
summary: Update a client
description: Updates an existing client with new details.
security:
- jwtAuth: []
requestBody:
description: The details to update
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ClientUpdate"
responses:
"200":
description: Client updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/query:
get:
operationId: listQueries
tags:
- QueryService
summary: List queries
description: Retrieves a list of queries based on filter criteria.
security:
- jwtAuth: []
responses:
"200":
description: A list of queries.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ListQueries"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
post:
operationId: createQuery
tags:
- QueryService
summary: Create a new query
description: Creates a new query with the provided details.
security:
- jwtAuth: []
requestBody:
description: The details required to create a query
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/QueryCreate"
responses:
"201":
description: Query created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/IdMessage"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/query/{id}:
parameters:
- $ref: "#/components/parameters/QueryID"
get:
operationId: getQuery
tags:
- QueryService
summary: Get a query by ID
description: Retrieves a specific query by its ID.
security:
- jwtAuth: []
responses:
"200":
description: Query details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/Query"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateQuery
tags:
- QueryService
summary: Update a query
description: Updates an existing query with new details.
security:
- jwtAuth: []
requestBody:
description: The update values for the desired query.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/QueryUpdate"
responses:
"200":
description: Query updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/query/{id}/test:
parameters:
- $ref: "#/components/parameters/QueryID"
post:
operationId: testQuery
tags:
- QueryService
summary: Test a query
description: Executes a test run of a query with the provided parameters.
security:
- jwtAuth: []
requestBody:
description: The query test requirements.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/QueryTestRequest"
responses:
"200":
description: Test result.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/QueryTestResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/status:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: getStatusByClientId
tags:
- ClientService
summary: Get client sync status
description: Retrieves the sync status by its client ID.
security:
- jwtAuth: []
responses:
"200":
description: Client status details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ClientStatusBody"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/collector:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: getCollectorByClientId
tags:
- CollectorService
summary: Get a collector by client ID
description: Retrieves a specific collector by its client ID.
security:
- jwtAuth: []
responses:
"200":
description: Collector details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/Collector"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: setCollectorByClientId
tags:
- CollectorService
summary: Set a collector
description: Set client collector with new details.
security:
- jwtAuth: []
requestBody:
description: The details to be set for the collector.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CollectorSet"
responses:
"204":
description: Collector set successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/document:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: listDocumentsByClientId
tags:
- DocumentsService
summary: List the documents for a client
description: Retrieves the list of documents by the client ID.
security:
- jwtAuth: []
responses:
"200":
description: Client documents list.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ListDocuments"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
post:
operationId: uploadDocument
tags:
- DocumentsService
summary: Upload a file
description: Upload a single file to the server with optional metadata
security:
- jwtAuth: []
requestBody:
required: true
description: upload file body
content:
multipart/form-data:
schema:
type: object
required:
- file
properties:
file:
type: string
format: binary
maxLength: 107374182400
description: The file to upload
filename:
type: string
pattern: ".+"
maxLength: 4096
description: Optional custom filename
example: "document.pdf"
encoding:
file:
contentType: application/pdf
style: form
explode: false
responses:
"200":
description: Document uploaded.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/document/batch:
parameters:
- $ref: "#/components/parameters/ClientID"
post:
operationId: uploadDocumentBatch
tags:
- DocumentsService
summary: Upload multiple PDF documents as ZIP archive
description: Upload a ZIP archive containing multiple PDF documents for async batch processing
security:
- jwtAuth: []
requestBody:
required: true
description: ZIP archive containing PDF documents
content:
multipart/form-data:
schema:
type: object
required:
- archive
properties:
archive:
type: string
format: binary
maxLength: 1073741824 # 1GB limit for ZIP files
description: The file to be uploaded as a ZIP archive
encoding:
archive:
contentType: application/zip
style: form
explode: false
responses:
"202":
description: Batch upload accepted for processing
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BatchUploadResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: listDocumentBatches
tags:
- DocumentsService
summary: List batch uploads for a client
description: Retrieves a list of batch uploads for the specified client
security:
- jwtAuth: []
parameters:
- in: query
name: limit
schema:
type: integer
format: int32
minimum: 1
maximum: 100
default: 20
description: Maximum number of items to return
- in: query
name: offset
schema:
type: integer
format: int32
minimum: 0
maximum: 2147483647
default: 0
description: Number of items to skip
responses:
"200":
description: List of batch uploads
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BatchUploadList"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/document/batch/{batch_id}:
parameters:
- $ref: "#/components/parameters/ClientID"
- $ref: "#/components/parameters/BatchID"
get:
operationId: getDocumentBatch
tags:
- DocumentsService
summary: Get batch upload status
description: Retrieves detailed status information for a specific batch upload
security:
- jwtAuth: []
responses:
"200":
description: Batch upload details
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BatchUploadDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: cancelDocumentBatch
tags:
- DocumentsService
summary: Cancel a batch upload
description: Cancels a batch upload that is currently processing
security:
- jwtAuth: []
responses:
"204":
description: Batch upload cancelled successfully
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/document/{id}:
parameters:
- $ref: "#/components/parameters/DocumentID"
get:
operationId: getDocument
tags:
- DocumentsService
summary: Get document details by its id
description: Retrieves the details of a document by its id.
security:
- jwtAuth: []
responses:
"200":
description: Document details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/Document"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/export:
parameters:
- $ref: "#/components/parameters/ClientID"
post:
operationId: triggerExport
tags:
- ExportService
summary: Trigger an export
description: Initiates the export process.
security:
- jwtAuth: []
requestBody:
description: The export requirements.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ExportTrigger"
responses:
"201":
description: Export triggered successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/IdMessage"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/export/{id}:
parameters:
- $ref: "#/components/parameters/ExportID"
get:
operationId: exportState
tags:
- ExportService
summary: Check export state.
description: Checks the current state of an export.
security:
- jwtAuth: []
responses:
"200":
description: Export has been completed.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ExportDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/login:
get:
operationId: login
tags:
- AuthService
summary: Login to the application
description: >-
Initiates the login flow by redirecting to Cognito IDP login page.
security:
- {}
- cognitoAuth: [openid, email, profile]
responses:
"302":
description: Redirect to Cognito login page
headers:
Location:
schema:
type: string
format: uri
maxLength: 2048
pattern: "^https://.*"
description: URL to the Cognito login page
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/login-callback:
get:
operationId: loginCallback
tags:
- AuthService
summary: OAuth2 callback endpoint
description: >-
Handles the OAuth2 callback during the login process. Receives the
authorization code from Cognito IDP and exchanges it for tokens.
security:
- {}
parameters:
- name: code
in: query
description: Authorization code from Cognito
required: true
schema:
type: string
maxLength: 2048
pattern: "^[A-Za-z0-9\\-_]+$"
- name: state
in: query
description: State parameter for CSRF protection
required: true
schema:
type: string
maxLength: 1024
pattern: "^[A-Za-z0-9\\-_]+$"
responses:
"302":
description: Redirect to application after successful login
headers:
Location:
schema:
type: string
format: uri
maxLength: 2048
pattern: "^https?://.*"
description: URL to redirect after successful login
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/logout:
get:
operationId: logout
tags:
- AuthService
summary: Logout from the application
description: >-
Logs the user out by invalidating the session and redirecting to
Cognito logout endpoint.
security:
- jwtAuth: []
responses:
"302":
description: Redirect to Cognito logout page or application home page
headers:
Location:
schema:
type: string
format: uri
maxLength: 2048
pattern: "^https?://.*"
description: URL to redirect after logout
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/home:
get:
operationId: getHomePage
tags:
- AuthService
summary: Get the home page menu
description: >-
Returns the HTML menu page for authenticated users.
security:
- jwtAuth: []
responses:
"200":
description: Home page HTML
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
text/html:
schema:
type: string
description: HTML content for the home page menu
maxLength: 1048576
pattern: "^.*$"
format: html
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/users:
post:
operationId: createAdminUser
tags:
- AdminService
summary: Create a new user
description: >-
Creates a new user in both AWS Cognito and Permit.io systems with optional role assignments.
Idempotent - returns 200 OK if user already exists with identical attributes.
**Creation Flow:**
1. User is created in AWS Cognito (primary authentication system)
2. If Cognito creation fails, operation fails with HTTP 502 (no user created)
3. User is created in Permit.io (authorization/role system)
4. If Permit.io creation fails, user still exists in Cognito but permit_synced=false
5. Roles are assigned in Permit.io (best-effort, continues on failures)
**Role Assignment Behavior:**
- Roles must exist in your Permit.io environment (e.g., super_admin, user_admin, auditor, client_user)
- Invalid/non-existent roles fail silently and are logged server-side
- Only successfully assigned roles appear in the roles_assigned response field
- The roles_assigned array may be a subset of the requested roles array
- If all roles fail, roles_assigned will be null or empty (user has no permissions)
**Partial Success Scenarios:**
- Returns HTTP 201 even if Permit.io creation or some role assignments fail
- Check permit_synced field: false indicates user was not created in Permit.io
- Compare roles_assigned vs requested roles to detect role assignment failures
- User can authenticate (Cognito) but may lack authorization (Permit.io) if sync fails
security:
- jwtAuth: []
requestBody:
description: The user details required to create a user
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserCreate"
responses:
"201":
description: User created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserCreateResponse"
"200":
description: User already exists with matching attributes (idempotent).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserCreateResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"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"
"502":
$ref: "#/components/responses/BadGateway"
get:
operationId: listAdminUsers
tags:
- AdminService
summary: List users
description: >-
Lists users from AWS Cognito with pagination, filtering, and sorting support.
security:
- jwtAuth: []
parameters:
- name: page
in: query
description: Page number for pagination
schema:
type: integer
format: int32
minimum: 1
default: 1
maximum: 10000
- name: page_size
in: query
description: Number of results per page
schema:
type: integer
format: int32
minimum: 1
maximum: 100
default: 50
- name: search
in: query
description: Search term for email/name filtering
schema:
type: string
maxLength: 256
pattern: "^.+$"
- name: status
in: query
description: Filter by user status
schema:
type: string
enum: [enabled, disabled, all]
default: all
- name: sort_by
in: query
description: Field to sort by
schema:
type: string
enum: [email, created_at, last_name]
default: email
- name: sort_order
in: query
description: Sort direction
schema:
type: string
enum: [asc, desc]
default: asc
responses:
"200":
description: List of users.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserList"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/users/{email}:
parameters:
- $ref: "#/components/parameters/UserEmail"
get:
operationId: getAdminUser
tags:
- AdminService
summary: Get user by email
description: >-
Retrieves user details from both AWS Cognito and Permit.io by email address.
security:
- jwtAuth: []
responses:
"200":
description: User details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"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"
head:
operationId: checkAdminUserExists
tags:
- AdminService
summary: Check if user exists
description: >-
Checks if a user exists in Cognito and/or Permit.io without returning full details.
security:
- jwtAuth: []
responses:
"200":
description: User exists.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
X-User-Exists-Cognito:
schema:
type: boolean
description: Whether user exists in Cognito
X-User-Exists-PermitIO:
schema:
type: boolean
description: Whether user exists in Permit.io
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
description: User does not exist in either system
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateAdminUser
tags:
- AdminService
summary: Update user attributes and roles
description: >-
Updates user attributes (first_name, last_name) in Cognito and manages role assignments in Permit.io.
Email address cannot be changed (use email path parameter to identify user).
**Attribute Updates:**
- first_name and last_name are updated in AWS Cognito
- Omit fields you don't want to change (e.g., send only roles to change roles)
**Role Management (REPLACE Strategy):**
- Providing a roles array REPLACES all existing roles (not additive)
- To add a role: include ALL current roles PLUS the new role
- To remove a role: include only the roles you want to keep
- To remove all roles: send an empty array []
- Omitting the roles field leaves role assignments unchanged
**Role Assignment Behavior:**
- Roles must exist in your Permit.io environment
- Invalid/non-existent roles fail silently and are logged server-side
- Response.roles field shows the final state after successful assignments
- Compare response.roles vs requested roles to detect failures
**Example - Add a Role:**
Current roles: ["client_user"]
To add "auditor": send roles: ["client_user", "auditor"]
Result: ["client_user", "auditor"]
**Example - Replace All Roles:**
Current roles: ["auditor", "client_user"]
To change to just "super_admin": send roles: ["super_admin"]
Result: ["super_admin"] (auditor and client_user removed)
security:
- jwtAuth: []
requestBody:
description: The user attributes to update
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserUpdate"
responses:
"200":
description: User updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"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"
delete:
operationId: deleteAdminUser
tags:
- AdminService
summary: Delete user permanently
description: >-
Permanently deletes a user from both AWS Cognito and Permit.io.
This operation is irreversible. Requires confirm=true query parameter.
security:
- jwtAuth: []
parameters:
- name: confirm
in: query
description: Must be set to true to confirm deletion
required: true
schema:
type: boolean
responses:
"200":
description: User deleted successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDeleteResponse"
"207":
description: User partially deleted (multi-status).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDeleteResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"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"
/admin/users/{email}/disable:
parameters:
- $ref: "#/components/parameters/UserEmail"
post:
operationId: disableAdminUser
tags:
- AdminService
summary: Disable user
description: >-
Disables a user in AWS Cognito, preventing authentication.
User data and roles are preserved. Idempotent.
security:
- jwtAuth: []
responses:
"200":
description: User disabled successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserActionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"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"
/admin/users/{email}/enable:
parameters:
- $ref: "#/components/parameters/UserEmail"
post:
operationId: enableAdminUser
tags:
- AdminService
summary: Enable user
description: >-
Re-enables a previously disabled user in AWS Cognito.
Restores authentication capability. Idempotent.
security:
- jwtAuth: []
responses:
"200":
description: User enabled successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserActionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"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"
components:
parameters:
ClientID:
in: path
name: id
required: true
schema:
$ref: "#/components/schemas/ClientID"
description: The client ID.
ExportID:
in: path
name: id
required: true
schema:
$ref: "#/components/schemas/ExportID"
description: The export ID.
QueryID:
in: path
name: id
required: true
schema:
$ref: "#/components/schemas/QueryID"
description: The ID of the query.
DocumentID:
in: path
name: id
required: true
schema:
$ref: "#/components/schemas/DocumentID"
description: The document ID.
BatchID:
in: path
name: batch_id
required: true
schema:
$ref: "#/components/schemas/BatchID"
description: The batch upload ID.
UserEmail:
in: path
name: email
required: true
schema:
type: string
format: email
maxLength: 320
description: URL-encoded user email address.
headers:
RateLimit:
schema:
type: string
pattern: "^[0-9]+;window=[0-9]+$"
maxLength: 32
example: 100;window=60
description: Rate limit information in format "limit;window=time-window"
example: "100;window=10"
securitySchemes:
jwtAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: >-
JWT token obtained after Cognito authentication. Implements RFC8725 JWT
best practices for security.
cognitoAuth:
type: oauth2
description: >-
Authentication using Amazon Cognito IDP. Implements RFC8725 JWT best
practices for security.
flows:
authorizationCode:
authorizationUrl: >-
https://doczy.auth.us-east-1.amazoncognito.com/oauth2/authorize
tokenUrl: >-
https://doczy.auth.us-east-1.amazoncognito.com/oauth2/token
scopes:
openid: Get OIDC token
email: Access to user's email
profile: Access to user's profile
responses:
InvalidRequest:
description: Invalid request body.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
InternalError:
description: Internal server error.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
TooManyRequests:
description: Response upon too many requests.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
Retry-After:
schema:
type: integer
format: int32
minimum: 0
maximum: 86400
description: Number of seconds before trying again.
example: 120
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
Unauthorized:
description: Response when unauthorized.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
NotFound:
description: Resource not found.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
Forbidden:
description: Insufficient permissions to perform this action.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
Conflict:
description: Resource already exists or state conflict.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
BadGateway:
description: External service error.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
schemas:
# Query API schemas
ClientID:
type: string
description: The client external id
example: AAA
maxLength: 36
pattern: "^.+$"
QueryID:
type: string
format: uuid
description: The query id.
example: 019580df-ef65-7676-8de9-94435a93337a
maxLength: 36
DocumentID:
type: string
format: uuid
description: The document id.
example: 019580df-b3f8-7348-9ab1-1e55b3f18ed7
maxLength: 36
ExportID:
type: string
format: uuid
description: The export id.
example: 019580de-4d51-713c-98ee-464e83811f13
maxLength: 36
BatchID:
type: string
format: uuid
description: The batch upload id.
example: 019580df-ef65-7676-8de9-94435a93337a
maxLength: 36
BatchStatus:
type: string
enum:
- processing
- completed
- failed
- cancelled
description: The status of a batch upload
BatchUploadResponse:
type: object
description: Response returned when a batch upload is accepted for processing
required:
- batch_id
- status
- status_url
properties:
batch_id:
$ref: "#/components/schemas/BatchID"
status:
$ref: "#/components/schemas/BatchStatus"
status_url:
type: string
format: uri-reference
maxLength: 512
description: URL to check batch status
example: "/client/AAA/document/batch/019580df-ef65-7676-8de9-94435a93337a"
BatchUploadSummary:
type: object
description: Summary information about a batch upload
required:
- batch_id
- client_id
- original_filename
- status
- total_documents
- processed_documents
- failed_documents
- invalid_type_documents
- progress_percent
- created_at
properties:
batch_id:
$ref: "#/components/schemas/BatchID"
client_id:
$ref: "#/components/schemas/ClientID"
original_filename:
type: string
maxLength: 4096
pattern: "^.+$"
description: Original filename of the uploaded ZIP archive
example: "documents.zip"
status:
$ref: "#/components/schemas/BatchStatus"
total_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of documents in the batch
example: 100
processed_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of documents processed so far
example: 42
failed_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of documents that failed processing
example: 2
invalid_type_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of non-PDF files found in archive
example: 1
progress_percent:
type: integer
format: int32
minimum: 0
maximum: 100
description: Processing progress percentage
example: 42
created_at:
type: string
format: date-time
maxLength: 50
description: When the batch upload was created
completed_at:
type: string
format: date-time
maxLength: 50
nullable: true
description: When the batch upload completed processing
BatchUploadDetails:
description: Detailed information about a batch upload including failed filenames
allOf:
- $ref: "#/components/schemas/BatchUploadSummary"
- type: object
properties:
failed_filenames:
type: array
maxItems: 10000
items:
type: string
maxLength: 4096
pattern: "^.+$"
description: List of filenames that failed processing
example: ["doc3.pdf", "doc17.pdf"]
BatchUploadList:
type: object
description: List of batch uploads for a client
required:
- batches
- total_count
properties:
batches:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/BatchUploadSummary"
total_count:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of batches for this client
example: 25
ClientName:
type: string
description: The client name
example: AArete
maxLength: 256
pattern: "^.+$"
ClientCanSync:
type: boolean
description: If the client is allowing active syncs
QueryType:
type: string
enum:
- JSON_EXTRACTOR
- CONTEXT_FULL
description: Specifies the type of the query.
QueryConfig:
type: string
description: Configuration for the query.
maxLength: 2048
pattern: '^\{.*\}$'
Query:
description: A logic unit of execution.
type: object
properties:
id:
$ref: "#/components/schemas/QueryID"
type:
$ref: "#/components/schemas/QueryType"
active_version:
$ref: "#/components/schemas/Version"
latest_version:
$ref: "#/components/schemas/Version"
config:
$ref: "#/components/schemas/QueryConfig"
required_queries:
$ref: "#/components/schemas/RequiredQueryIDs"
required:
- id
- type
- active_version
- latest_version
ListQueries:
description: A set of queries.
type: object
properties:
queries:
type: array
maxItems: 512
items:
$ref: "#/components/schemas/Query"
description: List of queries.
required:
- queries
QueryCreate:
description: The parameters required to create a query.
type: object
properties:
type:
$ref: "#/components/schemas/QueryType"
config:
$ref: "#/components/schemas/QueryConfig"
required_queries:
$ref: "#/components/schemas/RequiredQueryIDs"
required:
- type
RequiredQueryIDs:
type: array
maxItems: 256
items:
$ref: "#/components/schemas/QueryID"
description: List of required query IDs.
QueryUpdate:
description: The properties that may be updated for a query.
type: object
properties:
config:
$ref: "#/components/schemas/QueryConfig"
active_version:
$ref: "#/components/schemas/Version"
required_queries:
$ref: "#/components/schemas/RequiredQueryIDs"
QueryTestRequest:
description: The properties for a query test request.
type: object
properties:
document_id:
$ref: "#/components/schemas/DocumentID"
query_version:
$ref: "#/components/schemas/Version"
required:
- document_id
- query_version
QueryTestResponse:
description: The response from a query test.
type: object
properties:
value:
type: string
description: Result of the query test.
pattern: "^.+$"
maxLength: 2048
required:
- value
DocClient:
description: The properties of a client.
type: object
properties:
id:
$ref: "#/components/schemas/ClientID"
name:
$ref: "#/components/schemas/ClientName"
can_sync:
$ref: "#/components/schemas/ClientCanSync"
required:
- id
- name
- can_sync
ClientStatus:
type: string
enum:
- IN_SYNC
- NOT_SYNCED
- NOT_SYNCING
description: Specifies the status of a client.
ClientStatusBody:
description: A client status information object.
type: object
properties:
status:
$ref: "#/components/schemas/ClientStatus"
required:
- status
ClientIDBody:
description: The client id.
type: object
properties:
id:
$ref: "#/components/schemas/ClientID"
required:
- id
ListDocuments:
type: array
description: The documents in the client.
maxItems: 256
items:
$ref: "#/components/schemas/DocumentSummary"
Hash:
type: string
description: The document hash
maxLength: 2048
pattern: "^.+$"
DocumentSummary:
description: The document summary properties.
type: object
properties:
id:
$ref: "#/components/schemas/DocumentID"
hash:
$ref: "#/components/schemas/Hash"
required:
- id
- hash
Document:
description: The document properties.
type: object
properties:
id:
$ref: "#/components/schemas/DocumentID"
client_id:
$ref: "#/components/schemas/ClientID"
hash:
$ref: "#/components/schemas/Hash"
fields:
type: object
description: "The fields and the value for the document"
example:
property1: "string value"
property2: 42
property3: true
property5: [1, 2, 3]
required:
- id
- client_id
- hash
- fields
ClientCreate:
description: The properties for creation.
type: object
properties:
id:
$ref: "#/components/schemas/ClientID"
name:
$ref: "#/components/schemas/ClientName"
required:
- id
- name
ClientUpdate:
description: The properties that may be updated.
type: object
properties:
name:
$ref: "#/components/schemas/ClientName"
can_sync:
$ref: "#/components/schemas/ClientCanSync"
IdMessage:
description: A single uuid.
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier for entity.
maxLength: 36
required:
- id
CodeVersion:
type: integer
format: int64
minimum: 1
maximum: 9223372036854775808
description: The desired code version.
Version:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: The desired version.
Collector:
type: object
properties:
client_id:
$ref: "#/components/schemas/ClientID"
active_version:
$ref: "#/components/schemas/Version"
latest_version:
$ref: "#/components/schemas/Version"
minimum_cleaner_version:
$ref: "#/components/schemas/CodeVersion"
minimum_text_version:
$ref: "#/components/schemas/CodeVersion"
fields:
$ref: "#/components/schemas/CollectorFields"
description: Collector model.
required:
- client_id
- fields
- minimum_cleaner_version
- minimum_text_version
- latest_version
- active_version
CollectorFields:
type: array
maxItems: 256
description: The fields in the collector.
items:
$ref: "#/components/schemas/CollectorField"
CollectorSet:
type: object
properties:
minimum_cleaner_version:
$ref: "#/components/schemas/CodeVersion"
minimum_text_version:
$ref: "#/components/schemas/CodeVersion"
active_version:
$ref: "#/components/schemas/Version"
fields:
$ref: "#/components/schemas/CollectorFields"
description: Payload for updating a Collector.
CollectorFieldName:
type: string
pattern: "^.+$"
maxLength: 256
description: The output field name.
CollectorField:
type: object
description: The field properties for the collector.
properties:
name:
$ref: "#/components/schemas/CollectorFieldName"
query_id:
$ref: "#/components/schemas/QueryID"
required:
- name
- query_id
ExportTrigger:
type: object
properties:
ingestion_filters:
type: object
description: Filter the scope based on ingestion parameters.
properties:
start_date:
type: string
format: date-time
maxLength: 32
description: This first date of ingestion.
end_date:
type: string
format: date-time
maxLength: 32
description: The last date of ingestion.
field_filters:
type: array
maxItems: 256
description: Filter the scope based on field output values.
items:
$ref: "#/components/schemas/FieldFilter"
description: Payload for triggering an export.
FieldFilter:
type: object
properties:
field_name:
$ref: "#/components/schemas/CollectorFieldName"
condition:
$ref: "#/components/schemas/FieldFilterCondition"
values:
type: array
description: The values useful to the filter.
maxItems: 100
items:
type: string
pattern: "^.+$"
maxLength: 256
description: Filtering a column
required:
- field_name
- condition
- values
FieldFilterCondition:
type: string
enum:
- less_than
- greater_than
- closed_interval
- open_interval
- left_closed_interval
- right_closed_interval
- include
- exclude
description: The possible field filtering conditions.
ExportStatus:
type: string
enum:
- completed
- in_progress
- failed
description: The possible export states.
ExportDetails:
type: object
properties:
client_id:
$ref: "#/components/schemas/ClientID"
status:
$ref: "#/components/schemas/ExportStatus"
output_location:
type: string
description: The location in which the export zip file will be found.
example: s3://a/A/export/20250213/uuid.csv
maxLength: 2048
pattern: '^s3://.+/.+/export/[0-9]{8}/.+\.csv$'
description: Payload for export trigger response.
required:
- client_id
- status
ErrorMessage:
description: Description of error
type: object
properties:
message:
type: string
pattern: "^.+$"
description: Message describing the cause.
maxLength: 256
example: "you must give me good information"
required:
- message
example:
message: you must include a message
# Admin API schemas
AdminUserCreate:
description: Request body for creating a new user with email, name, and role assignments
type: object
required:
- email
- first_name
- last_name
- roles
properties:
email:
type: string
format: email
maxLength: 320
pattern: '^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$'
description: User email address (used as Cognito username)
example: john.doe@example.com
first_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: User's given name for account creation
example: John
last_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: User's family name for account creation
example: Doe
roles:
type: array
minItems: 1
maxItems: 50
items:
type: string
pattern: "^.+$"
maxLength: 100
description: >-
List of role keys to assign in Permit.io (e.g., super_admin, user_admin, auditor, client_user).
Roles must exist in your Permit.io environment. Invalid roles fail silently - check roles_assigned in response.
example: ["user_admin", "auditor"]
AdminUserCreateResponse:
description: Response after creating a user, including Cognito subject ID and sync status
type: object
required:
- cognito_subject_id
- email
- status
- permit_synced
properties:
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: Created user's Cognito unique subject identifier
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
email:
type: string
format: email
maxLength: 320
description: User email address
example: john.doe@example.com
first_name:
type: string
maxLength: 100
pattern: "^.+$"
description: Created user's given name
example: John
last_name:
type: string
maxLength: 100
pattern: "^.+$"
description: Created user's family name
example: Doe
status:
type: string
maxLength: 50
pattern: "^.+$"
description: Cognito user status
example: FORCE_CHANGE_PASSWORD
enabled:
type: boolean
description: Whether the created user is enabled in Cognito
example: true
permit_synced:
type: boolean
description: >-
Whether user was successfully created in Permit.io authorization system.
If false, user exists in Cognito (can authenticate) but not in Permit.io (has no authorization/permissions).
Manual sync or retry may be required.
example: true
roles_assigned:
type: array
maxItems: 50
items:
type: string
maxLength: 100
pattern: "^.+$"
description: >-
Roles that were successfully assigned in Permit.io. May be a subset of requested roles if some failed.
Compare with requested roles array to detect assignment failures. If null or empty, no roles were assigned
(user has no permissions). Only present if permit_synced is true.
example: ["user_admin", "auditor"]
created_at:
type: string
format: date-time
maxLength: 50
description: Timestamp when the user was created in the system
example: "2025-10-16T14:23:45Z"
AdminUserDetails:
description: Complete user information from Cognito and Permit.io including roles and timestamps
type: object
required:
- cognito_subject_id
- email
- status
- enabled
properties:
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: User's Cognito unique subject identifier from authentication system
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
email:
type: string
format: email
maxLength: 320
description: Email address of the user account
example: john.doe@example.com
first_name:
type: string
maxLength: 100
pattern: "^.+$"
description: User's given name retrieved from Cognito
example: John
last_name:
type: string
maxLength: 100
pattern: "^.+$"
description: User's family name retrieved from Cognito
example: Doe
status:
type: string
maxLength: 50
pattern: "^.+$"
description: Current Cognito user account status
example: CONFIRMED
enabled:
type: boolean
description: Current enabled status of the user in Cognito
example: true
roles:
type: array
maxItems: 50
items:
type: string
maxLength: 100
pattern: "^.+$"
description: Roles assigned in Permit.io
example: ["admin", "viewer"]
created_at:
type: string
format: date-time
maxLength: 50
description: Timestamp when the user account was created
example: "2025-10-15T09:15:30Z"
updated_at:
type: string
format: date-time
maxLength: 50
description: Timestamp of last update
example: "2025-10-16T14:20:10Z"
AdminUserUpdate:
description: Request body for updating user attributes (first name, last name, and roles)
type: object
properties:
first_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: Updated given name for the user
example: Jonathan
last_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: Updated family name for the user
example: Doe-Smith
roles:
type: array
minItems: 1
maxItems: 50
items:
type: string
pattern: "^.+$"
maxLength: 100
description: >-
Complete list of role keys to assign in Permit.io - REPLACES all existing roles (not additive).
To add a role, include all current roles plus the new one. To remove a role, omit it from the array.
Roles must exist in Permit.io environment. Invalid roles fail silently - check response.roles for final state.
Omit this field entirely to leave roles unchanged.
example: ["user_admin", "auditor"]
AdminUserList:
description: Paginated list of users with total count and pagination metadata
type: object
required:
- users
- total
- page
- page_size
properties:
users:
type: array
maxItems: 100
items:
$ref: '#/components/schemas/AdminUserDetails'
description: List of users for current page
total:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of users matching filter
example: 147
page:
type: integer
format: int32
minimum: 1
maximum: 10000
description: Current page number
example: 1
page_size:
type: integer
format: int32
minimum: 1
maximum: 100
description: Number of users per page
example: 20
has_more:
type: boolean
description: Whether more pages are available
example: true
AdminUserActionResponse:
description: Response for user enable/disable actions with success status and timestamp
type: object
required:
- success
- email
- action
properties:
success:
type: boolean
description: Whether the action succeeded
example: true
email:
type: string
format: email
maxLength: 320
description: Email of the user acted upon
example: john.doe@example.com
action:
type: string
enum: [disable, enable]
description: Action performed
example: disable
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: Cognito subject identifier for the action response
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
timestamp:
type: string
format: date-time
maxLength: 50
description: Timestamp of the action
example: "2025-10-16T14:25:33Z"
AdminUserDeleteResponse:
description: Response for user deletion with status from each system (Cognito and Permit.io)
type: object
required:
- success
- email
- deleted_from
properties:
success:
type: boolean
description: Whether the deletion succeeded
example: true
email:
type: string
format: email
maxLength: 320
description: Email of the deleted user
example: john.doe@example.com
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: Cognito subject identifier of the deleted user
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
deleted_from:
type: object
required:
- cognito
- permit
properties:
cognito:
type: boolean
description: Whether user was deleted from Cognito
example: true
permit:
type: boolean
description: Whether user was deleted from Permit.io
example: true
description: Deletion status from each system
timestamp:
type: string
format: date-time
maxLength: 50
description: Timestamp of the deletion
example: "2025-10-16T14:27:15Z"