openapi: 3.1.0 info: description: "Adaptive API for external integrations.\n\n## \uD83D\uDCCA API Overview\n\nThe Adaptive API enables organizations to build comprehensive reporting and analytics around their security awareness training programs. This RESTful API provides programmatic access to track employee training progress, monitor compliance, and generate insights about your organization's security training effectiveness.\n\n### Purpose & Use Cases\n\nThis API is designed for:\n- **Compliance Reporting**: Track training completion rates and identify employees with overdue trainings\n- **Progress Monitoring**: Get real-time visibility into individual and team training progress\n- **Data Integration**: Sync training data with your HRIS, BI tools, or custom dashboards\n- **Automated Workflows**: Build alerts and notifications for training milestones or compliance deadlines\n\n### Technical Design\n\nThe API follows REST principles with:\n- Resource-oriented URLs that clearly represent your data\n- Standard HTTP methods (GET for reading data)\n- JSON responses for easy parsing and integration\n- Consistent error handling with detailed error messages\n- Token-based authentication for secure access\n\n### Available Resources\n\n| Resource | Purpose | Common Use Cases |\n|----------|---------|------------------|\n| **Users** | Access employee directory data | • Export user lists for reporting
• Track user status changes
• Map users to departments |\n| **Training** | Monitor training campaigns and progress | • Track campaign completion rates
• Identify at-risk employees
• Generate compliance reports |\n\n## \uD83D\uDE80 Quick Start Guide\n\nGet started with the Adaptive API in just 3 steps:\n\n### Step 1: Get Your API Token\nSee [Authentication](#section/Authentication) for more details on how to generate and use API tokens.\n\n### Step 2: Make Your First API Call\n```bash\ncurl -X GET https://api.adaptivesecurity.com/v2/users \\\n -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\n### Step 3: Handle the Response\n```json\n{\n \"users\": [\n {\n \"id\": \"123e4567-e89b-12d3-a456-426614174000\",\n \"email\": \"john.smith@example.com\",\n \"first_name\": \"John\",\n \"last_name\": \"Smith\",\n \"status\": \"ACTIVE\"\n }\n ],\n \"page_after\": \"123e4567-e89b-12d3-a456-426614174000\"\n}\n```\n\n## \uD83D\uDD10 Authentication\n\nAll API endpoints require authentication using an API token:\n\n```http\nAuthorization: Bearer YOUR_API_TOKEN\n```\n\n**Token Management:**\n- Tokens are generated in the Admin portal under **Settings → API**\n- Tokens have a user-set expiration but can be revoked at any time\n- Store tokens securely - treat them like passwords\n## \uD83C\uDF10 Base URL\n\nAll API endpoints are relative to:\n```\nhttps://api.adaptivesecurity.com\n```\n\n## \uD83D\uDEA8 Error Handling\n\nAll API errors follow a consistent JSON structure:\n\n### Standard Error Response\n```json\n{\n \"error_code\": \"RESOURCE_NOT_FOUND\",\n \"message\": \"The requested user was not found\",\n \"status_code\": 404,\n \"request_id\": \"3e502c09-4fd3-42d3-8b3a-4e2f08de0bbf\"\n}\n```\n\n### Validation Error Response\n```json\n{\n \"error_code\": \"VALIDATION_ERROR\",\n \"message\": \"Request validation failed\",\n \"status_code\": 400,\n \"request_id\": \"1d7c1712-2b8e-43f4-90c6-1185e249bdf0\",\n \"details\": [\n {\n \"field\": \"page\",\n \"message\": \"Page must be a non-negative integer\"\n }\n ]\n}\n```\n\n### Error Code Reference\n| Code | Status | Description | Action |\n|------|--------|-------------|--------|\n| `INVALID_TOKEN` | 401 | Token is invalid or expired | Check token validity |\n| `RESOURCE_NOT_FOUND` | 404 | Resource doesn't exist | Verify resource ID |\n| `VALIDATION_ERROR` | 400 | Request validation failed | Check field errors |\n| `INTERNAL_SERVER_ERROR` | 500 | Server error | Contact support |\n\n## \uD83D\uDCCB Request & Response Headers\n\n### Required Request Headers\n```http\nAuthorization: Bearer YOUR_API_TOKEN\n```\n\n### Optional Request Headers\n```http\nAccept: application/json\nContent-Type: application/json # Required for POST/PUT\n```\n\n### Response Headers\n```http\nX-Request-ID: 6acb3ce1-672a-4a49-8fa1-f1a994eef9fd\nContent-Type: application/json\n```\n\n## \uD83D\uDCC4 Pagination\n\nList endpoints return paginated results for optimal performance:\n\n- **Page cursor**: `page_after` field in the response to get the next page\n- **Default sorting**: By creation date (newest first)\n\n### Pagination Example\n```bash\n# Get the next page of users\ncurl -X GET \"https://api.adaptivesecurity.com/v2/users?page_after=5a6dce1e-8d0f-46b1-b263-50b6adca62da\" \\\n -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\n### Pagination Response\n```json\n{\n \"users\": [...],\n \"page_after\": \"123e4567-e89b-12d3-a456-426614174000\"\n}\n```\n\n## \uD83D\uDD50 Timestamps\n\nAll timestamps use ISO 8601 format in UTC:\n```\n2024-12-10T15:30:45.402Z\n```" title: Adaptive Audit Logs Training API version: v2 servers: - url: https://api.adaptivesecurity.com description: Production API security: - bearer-token: [] tags: - description: 'BETATraining campaign and activity endpoints' name: Training paths: /v2/training/campaigns: get: description: 'BETARetrieve a paginated list of training campaigns' operationId: listTrainingCampaigns parameters: - description: Page cursor example: 6e8e3c89-1122-4db2-ae91-f2c6bc0d5639 in: query name: page_after required: false schema: type: string - description: Page size example: 100 in: query name: page_size required: false schema: type: integer default: 100 responses: '200': content: application/json: examples: Success Response: description: Success Response value: campaigns: - id: 2db2730a-3a9d-4b3d-87b4-1d16e1e66a88 name: Engineering Annual Training audience_type: GROUPS groups: - id: f95d3d85-284b-4f94-98fe-23914c805b88 name: Engineering Team mode: SCHEDULED status: IN_PROGRESS created_at: '2025-01-01T13:19:13.402Z' start_date: '2025-01-10T13:19:13.402Z' end_date: '2025-04-10T13:19:13.402Z' employee_title: 2024 Security Awareness Training - id: 6e8e3c89-1122-4db2-ae91-f2c6bc0d5639 name: New Employee Onboarding audience_type: ALL_USERS groups: [] mode: TRIGGERED status: IN_PROGRESS created_at: '2025-06-15T08:00:00Z' start_date: '2025-06-15T08:00:00Z' end_date: null employee_title: null page_after: 6e8e3c89-1122-4db2-ae91-f2c6bc0d5639 schema: $ref: '#/components/schemas/TrainingCampaignListResponseDto' description: Successfully retrieved training campaigns '400': content: application/json: examples: Validation Error: description: Validation Error value: error_code: VALIDATION_ERROR message: Request validation failed status_code: 400 request_id: 2f6f683d-c3e3-44c3-8ee2-b06b5687f255 details: - field: page_after message: page_after must be a string schema: $ref: '#/components/schemas/ValidationErrorResponseDto' description: Bad request - Invalid parameters '401': content: application/json: examples: Unauthorized Error: description: Unauthorized Error value: error_code: INVALID_TOKEN message: The provided authentication token is invalid or expired status_code: 401 request_id: 74fc4c18-2c80-4394-b2e2-2f137b237b92 schema: $ref: '#/components/schemas/ErrorResponseDto' description: Unauthorized - Invalid or missing authentication token '429': content: application/json: examples: Rate Limit Error: description: Rate Limit Error value: error_code: RATE_LIMIT_EXCEEDED message: API rate limit exceeded. Please retry after some time status_code: 429 request_id: 0d47b5d3-884b-42c5-a20a-04e47011ebf4 schema: $ref: '#/components/schemas/ErrorResponseDto' description: Too many requests - Rate limit exceeded '500': content: application/json: examples: Internal Server Error: description: Internal Server Error value: error_code: INTERNAL_SERVER_ERROR message: An unexpected error occurred. Please try again later status_code: 500 request_id: f7e20a42-3c64-4f45-8a87-76113a1ce2f0 schema: $ref: '#/components/schemas/ErrorResponseDto' description: Internal server error summary: List training campaigns tags: - Training /v2/training/campaigns/enrollments: get: description: 'BETARetrieve details about training enrollments with campaign and user filters' operationId: getTrainingCampaignEnrollments parameters: - description: User ID example: 123e4567-e89b-12d3-a456-426614174000 in: query name: user_id required: false schema: type: string - description: Training campaign ID example: c143c964-d39b-4f0f-b3d3-07bb3aaae71e in: query name: campaign_id required: false schema: type: string - description: Page cursor example: f248c6c3-9c93-4d62-a41b-9843de18f56b in: query name: page_after required: false schema: type: string - description: Number of enrollments to return per page (max 1000) example: 100 in: query name: page_size required: false schema: type: integer default: 100 responses: '200': content: application/json: examples: Success Response: description: Success Response value: enrollments: - id: 5a6dce1e-8d0f-46b1-b263-50b6adca62da user: id: 123e4567-e89b-12d3-a456-426614174000 email: john.smith@example.com campaign: id: e7f89a36-4b8f-4865-b11a-b0f280ae6a34 name: Q4 Security Training employee_title: 2024 Security Awareness Training status: IN_PROGRESS enrolled_at: '2024-10-05T09:15:00Z' due_at: '2024-10-12T09:20:00Z' started_at: '2024-10-05T09:20:00Z' unenrolled_at: null completed_at: null has_acknowledged_policy: false page_after: 5a6dce1e-8d0f-46b1-b263-50b6adca62da schema: $ref: '#/components/schemas/UserTrainingCampaignEnrollmentListDto' description: Successfully retrieved campaign enrollment details '401': content: application/json: examples: Unauthorized Error: description: Unauthorized Error value: error_code: INVALID_TOKEN message: The provided authentication token is invalid or expired status_code: 401 request_id: 5a7384c9-b5de-4aa1-a144-faa0de243ab0 schema: $ref: '#/components/schemas/ErrorResponseDto' description: Unauthorized - Invalid or missing authentication token '429': content: application/json: examples: Rate Limit Error: description: Rate Limit Error value: error_code: RATE_LIMIT_EXCEEDED message: API rate limit exceeded. Please retry after some time status_code: 429 request_id: 6e9d2fb1-95e2-49e2-ae36-9de6e6f51c25 schema: $ref: '#/components/schemas/ErrorResponseDto' description: Too many requests - Rate limit exceeded '500': content: application/json: examples: Internal Server Error: description: Internal Server Error value: error_code: INTERNAL_SERVER_ERROR message: An unexpected error occurred. Please try again later status_code: 500 request_id: a0a7b8e0-fc0b-46b1-8dbb-0d04872f9678 schema: $ref: '#/components/schemas/ErrorResponseDto' description: Internal server error summary: Get training campaign enrollments details tags: - Training /v2/training/campaigns/{campaignId}: get: description: 'BETARetrieve detailed information about a specific training campaign' operationId: getTrainingCampaign parameters: - description: Campaign ID example: e7f89a36-4b8f-4865-b11a-b0f280ae6a34 in: path name: campaignId required: true schema: type: string responses: '200': content: application/json: examples: Success Response: description: Success Response value: id: 88479a0e-6ef4-4bc9-9af1-d57bae0f1234 name: Engineering Annual Training audience_type: GROUPS groups: - id: 12345654-4321-1234-9abc-def012345678 name: Engineers mode: SCHEDULED status: IN_PROGRESS created_at: '2025-06-01T13:19:13.402Z' start_date: '2025-06-10T13:19:13.402Z' end_date: '2025-08-10T13:19:13.402Z' employee_title: 2024 Security Awareness Training schema: $ref: '#/components/schemas/TrainingCampaignDto' description: Successfully retrieved training campaign details '401': content: application/json: examples: Unauthorized Error: description: Unauthorized Error value: error_code: INVALID_TOKEN message: The provided authentication token is invalid or expired status_code: 401 request_id: dcaf9f7e-6c47-4c93-bb41-0e2d8d9bb0de schema: $ref: '#/components/schemas/ErrorResponseDto' description: Unauthorized - Invalid or missing authentication token '404': content: application/json: examples: Not Found Error: description: Not Found Error value: error_code: RESOURCE_NOT_FOUND message: The requested training campaign was not found status_code: 404 request_id: 2a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d schema: $ref: '#/components/schemas/ErrorResponseDto' description: Training campaign not found '500': content: application/json: examples: Internal Server Error: description: Internal Server Error value: error_code: INTERNAL_SERVER_ERROR message: An unexpected error occurred. Please try again later status_code: 500 request_id: f351ac3c-cd5e-4ec7-89dc-191fc40a83f2 schema: $ref: '#/components/schemas/ErrorResponseDto' description: Internal server error summary: Get training campaign details tags: - Training components: schemas: TrainingCampaignListResponseDto: type: object description: Paginated list of training campaigns properties: campaigns: type: array items: $ref: '#/components/schemas/TrainingCampaignDto' page_after: type: string example: 123e4567-e89b-12d3-a456-426614174000 CampaignGroupDto: type: object properties: id: type: string description: Unique identifier for the group example: e7f89a36-4b8f-4865-b11a-b0f280ae6a34 name: type: string description: The name of the group example: Finance Team UserTrainingCampaignEnrollmentListDto: type: object properties: enrollments: type: array items: $ref: '#/components/schemas/UserTrainingCampaignEnrollmentDto' page_after: type: string example: 3b495a63-23f2-4284-82d0-3aa5b5c0c753 TrainingCampaignSummaryDto: type: object description: Training campaign information properties: id: type: string description: Unique identifier for the campaign example: e7f89a36-4b8f-4865-b11a-b0f280ae6a34 name: type: string description: Name of the training campaign example: Engineering Annual Training employee_title: type: - string - 'null' description: Employee-facing title for the campaign. Null if no employee-facing title is set. example: 2024 Annual Security Training UserTrainingCampaignEnrollmentDto: type: object description: User's enrollment details for a training campaign properties: campaign: $ref: '#/components/schemas/TrainingCampaignSummaryDto' completed_at: type: string format: date-time example: '2025-01-01T13:19:13.402Z' due_at: type: string format: date-time description: Date when the user's training completion is due example: '2025-01-08T13:19:13.402Z' enrolled_at: type: string format: date-time example: '2025-01-01T13:19:13.402Z' has_acknowledged_policy: type: boolean example: false id: type: string description: Unique identifier for the enrollment example: 6a10d54c-f1bf-4d1d-8864-64bfac9a0c13 started_at: type: string format: date-time description: Date when user started the training example: '2025-01-01T13:19:13.402Z' status: type: string description: User's enrollment status in the training campaign enum: - IN_PROGRESS - COMPLETED - INCOMPLETE - OVERDUE - UNENROLLED example: IN_PROGRESS unenrolled_at: type: string format: date-time example: '2025-01-02T13:19:13.402Z' user: $ref: '#/components/schemas/UserSummaryDto' ValidationErrorResponseDto: type: object description: Error response for validation failures with field-level details properties: details: type: array description: List of field-level validation error details items: $ref: '#/components/schemas/ErrorDetail' error_code: type: string description: Machine-readable error code example: VALIDATION_ERROR message: type: string description: Human-readable error message example: Request validation failed request_id: type: string description: Unique request ID for debugging example: 8f03bdf9-ac45-4279-8dbe-f28839c2fed3 status_code: type: integer format: int32 description: HTTP status code example: 400 required: - details - error_code - message - request_id - status_code UserSummaryDto: type: object description: User summary information properties: email: type: string description: User's email address example: john.smith@example.com id: type: string description: Unique identifier for the user example: 123e4567-e89b-12d3-a456-426614174000 ErrorDetail: type: object description: Field-level validation error details properties: field: type: string description: Field name that failed validation example: email message: type: string description: Validation error message for this field example: Email address is not valid required: - field - message ErrorResponseDto: type: object description: Standard error response format for all API errors properties: error_code: type: string description: Machine-readable error code example: RESOURCE_NOT_FOUND message: type: string description: Human-readable error message example: The requested user was not found request_id: type: string description: Unique request ID for debugging example: 8f03bdf9-ac45-4279-8dbe-f28839c2fed3 status_code: type: integer format: int32 description: HTTP status code example: 404 required: - error_code - message - request_id - status_code TrainingCampaignDto: type: object description: Training campaign information properties: audience_type: type: string description: Target audience type for the campaign enum: - GROUPS - ALL_USERS example: GROUPS created_at: type: string format: date-time description: Campaign's created date example: '2025-01-01T13:19:13.402Z' end_date: type: string format: date-time description: End date for the campaign (null for TRIGGERED mode) example: '2025-01-01T13:19:13.402Z' groups: type: array description: Groups associated with the campaign items: $ref: '#/components/schemas/CampaignGroupDto' id: type: string description: Unique identifier for the campaign example: e7f89a36-4b8f-4865-b11a-b0f280ae6a34 mode: type: string description: Campaign mode enum: - SCHEDULED - TRIGGERED example: SCHEDULED name: type: string description: Name of the training campaign example: Engineering Annual Training start_date: type: string format: date-time description: Start date for the campaign example: '2025-01-01T13:19:13.402Z' status: type: string description: Current status of the campaign enum: - DRAFT - SCHEDULED - IN_PROGRESS - COMPLETED - OVERDUE example: IN_PROGRESS employee_title: type: - string - 'null' description: Employee-facing title for the campaign. Null if no employee-facing title is set. example: 2024 Annual Security Training securitySchemes: bearer-token: description: 'API authentication token obtained from the Adaptive Admin portal (Settings → API Tokens). Include the token in the Authorization header as: Bearer YOUR_TOKEN' scheme: bearer type: http