{
  "openapi": "3.1.0",
  "info": {
    "title": "Cybr Labs public integration API",
    "version": "0.0.15",
    "description": "SDK and REST integration contract. Organization keys remain on the server.",
    "contact": {
      "email": "support@cybr.com"
    }
  },
  "servers": [
    {
      "url": "https://api.cybr.com"
    }
  ],
  "security": [
    {
      "OrganizationKey": []
    }
  ],
  "tags": [
    {
      "name": "Labs",
      "description": "Content, progress, discussions, and resource links."
    },
    {
      "name": "Deployments",
      "description": "Lab environments and terminal sessions."
    }
  ],
  "paths": {
    "/api/v2/labs": {
      "get": {
        "operationId": "list_labs",
        "summary": "List labs",
        "description": "Returns the organization catalog with its customizations. SDK: `labs.list()`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.list()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Lab"
                  }
                },
                "example": [
                  {
                    "id": "lab_id",
                    "name": "Example lab",
                    "slug": "example-lab",
                    "description": "An isolated exercise.",
                    "provider": "aws",
                    "timeLimit": 30,
                    "estimatedLaunchSeconds": 120,
                    "ctf": true,
                    "free": true,
                    "createdAt": "2026-01-01T00:00:00Z",
                    "updatedAt": "2026-01-01T00:00:00Z",
                    "hasGuide": false,
                    "hasResources": false,
                    "hasVideos": false,
                    "hasWriteups": false,
                    "webTerminal": true
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Access denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/labs/{labId}": {
      "get": {
        "operationId": "get_lab",
        "summary": "Get lab",
        "description": "Returns public content and optional learner-specific completion. SDK: `labs.get(labId, { learnerId })`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.get(labId, { learnerId })",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LabDetails"
                },
                "example": {
                  "id": "lab_id",
                  "name": "Example lab",
                  "slug": "example-lab",
                  "description": "An isolated exercise.",
                  "provider": "aws",
                  "timeLimit": 30,
                  "estimatedLaunchSeconds": 120,
                  "ctf": true,
                  "free": true,
                  "createdAt": "2026-01-01T00:00:00Z",
                  "updatedAt": "2026-01-01T00:00:00Z",
                  "bannerUrl": null,
                  "webTerminal": true,
                  "guide": null,
                  "resources": null,
                  "diagrams": [],
                  "videos": [],
                  "writeups": [],
                  "completed": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Access denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "labId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "learnerId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v2/deployments": {
      "post": {
        "operationId": "launch_deployment",
        "summary": "Launch deployment",
        "description": "Starts a lab environment. Acceptance does not mean readiness. REST requires membership. SDK: `deployments.launch()`.",
        "tags": [
          "Deployments"
        ],
        "x-sdk-method": "deployments.launch()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LaunchResponse"
                },
                "example": {
                  "deploymentId": "deployment_id",
                  "version": "v2"
                }
              }
            }
          },
          "400": {
            "description": "Invalid launch input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Access denied or inactive subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lab not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Learner launch limit or organization capacity reached. Read retryAfter or activeCount and limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporary deployment capacity unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LaunchRequest"
              },
              "example": {
                "labId": "lab_id",
                "learnerId": "academy:user:uuid",
                "membership": "free"
              }
            }
          }
        }
      }
    },
    "/api/v2/deployments/{deploymentId}": {
      "get": {
        "operationId": "get_deployment",
        "summary": "Get deployment status",
        "description": "Returns deployment readiness. Status complete does not mean learner completion. SDK: `deployments.getStatus()`.",
        "tags": [
          "Deployments"
        ],
        "x-sdk-method": "deployments.getStatus()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentStatus"
                },
                "example": {
                  "status": "complete",
                  "outputs": {
                    "console_url": {
                      "value": "https://example.com/console",
                      "sensitive": true,
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Access denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "deploymentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v2/deployments/{deploymentId}/runs": {
      "get": {
        "operationId": "get_runs",
        "summary": "Get deployment runs",
        "description": "Returns build and teardown runs. An unknown deployment or one outside organization access returns an empty array. Run output can contain secrets. SDK: `deployments.getRuns()`.",
        "tags": [
          "Deployments"
        ],
        "x-sdk-method": "deployments.getRuns()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DeploymentRun"
                  }
                },
                "example": []
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Access denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "deploymentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v2/deployments/{deploymentId}/destroy": {
      "post": {
        "operationId": "end_deployment",
        "summary": "End deployment",
        "description": "Starts teardown. It does not record learner completion. SDK: `deployments.destroy()`.",
        "tags": [
          "Deployments"
        ],
        "x-sdk-method": "deployments.destroy()",
        "responses": {
          "202": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DestroyResponse"
                },
                "example": {
                  "deploymentId": "deployment_id"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Deployment not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Deployment state does not permit teardown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "Teardown accepted while provisioning, or already in progress.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DestroyResponse"
                },
                "example": {
                  "deploymentId": "deployment_id"
                }
              }
            }
          },
          "502": {
            "description": "RUNNER_UNAVAILABLE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "deploymentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v2/deployments/{deploymentId}/terminal-session": {
      "post": {
        "operationId": "create_terminal_session",
        "summary": "Create terminal session",
        "description": "Creates temporary WebSocket credentials. Keep the response private and request fresh credentials for each reconnect. SDK: `deployments.createTerminalSession()`.",
        "tags": [
          "Deployments"
        ],
        "x-sdk-method": "deployments.createTerminalSession()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TerminalSession"
                },
                "example": {
                  "wsUrl": "wss://terminal.example.com/session",
                  "protocols": [
                    "cybr-terminal",
                    "example-token"
                  ],
                  "expiresAt": "2026-01-01T00:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "INVALID_DEPLOYMENT_ID or NO_TERMINAL_CREDENTIALS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "DEPLOYMENT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "INVALID_DEPLOYMENT_STATUS, TERMINAL_NOT_ENABLED, TERMINAL_NOT_SUPPORTED, LAB_ENDED, NO_TERMINAL_ROLE, or TERMINAL_ENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "CONTAINER_STARTING, TERMINAL_NOT_CONFIGURED, or TERMINAL_UNAVAILABLE. Only CONTAINER_STARTING uses the SDK startup retry loop.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "deploymentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v2/labs/{labId}/flag": {
      "post": {
        "operationId": "submit_flag",
        "summary": "Submit flag",
        "description": "Grades the flag. A correct result records completion. Incorrect verdicts also use HTTP 200. SDK: `labs.submitFlag()`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.submitFlag()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlagResponse"
                },
                "example": {
                  "message": "CORRECT_FLAG"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lab not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "COMPLETION_RECORD_FAILED or server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "labId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FlagRequest"
              },
              "example": {
                "learnerId": "academy:user:uuid",
                "flag": "example-flag"
              }
            }
          }
        }
      }
    },
    "/api/v2/labs/{labId}/guide/answer": {
      "post": {
        "operationId": "grade_answer",
        "summary": "Grade guide answer",
        "description": "Grades one knowledge check. It does not record lab completion. The learnerId field is accepted but currently unused. SDK: `labs.submitGuideAnswer()`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.submitGuideAnswer()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnswerResponse"
                },
                "example": {
                  "message": "CORRECT_ANSWER"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Access denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "labId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnswerRequest"
              },
              "example": {
                "taskId": "task_id",
                "answer": true
              }
            }
          }
        }
      }
    },
    "/api/v2/labs/{labId}/complete": {
      "post": {
        "operationId": "record_completion",
        "summary": "Record completion",
        "description": "Records application-reported completion for a non-CTF lab. Repeated successful requests create new records. SDK: `labs.markCompleted()`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.markCompleted()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompletionResponse"
                },
                "example": {
                  "message": "COMPLETED"
                }
              }
            }
          },
          "400": {
            "description": "Invalid learner ID, malformed JSON, or FLAG_REQUIRED for a CTF lab.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lab not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request body exceeds 1,000,000 UTF-8 bytes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "COMPLETION_RECORD_FAILED or server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "labId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompletionRequest"
              },
              "example": {
                "learnerId": "academy:user:uuid"
              }
            }
          }
        }
      }
    },
    "/api/v2/labs/{labId}/comments": {
      "get": {
        "operationId": "list_comments",
        "summary": "List comments",
        "description": "Returns organization-scoped discussion threads and replies. SDK: `labs.listComments()`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.listComments()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommentsPage"
                },
                "example": {
                  "comments": [],
                  "nextCursor": null,
                  "totalCount": 0
                }
              }
            }
          },
          "400": {
            "description": "Invalid cursor, limit, or learner header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Organization API key required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lab not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Discussion read limit reached. Read the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "labId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-cybr-learner-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            },
            "description": "Learner ID from the server session."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          }
        ]
      },
      "post": {
        "operationId": "create_comment",
        "summary": "Create comment",
        "description": "Creates a top-level comment or a reply to a top-level comment. SDK: `labs.createComment()`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.createComment()",
        "responses": {
          "201": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Comment"
                },
                "example": {
                  "id": "comment_id",
                  "authorName": "Learner",
                  "body": "Example question",
                  "createdAt": "2026-01-01T00:00:00Z",
                  "ownedByViewer": true,
                  "deleted": false,
                  "replies": []
                }
              }
            }
          },
          "400": {
            "description": "Invalid body or learner header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Organization API key required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lab or parent comment not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Reply limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request body exceeds 16 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Discussion write limit reached. Read the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "labId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-cybr-learner-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            },
            "description": "Learner ID from the server session."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCommentRequest"
              },
              "example": {
                "body": "Example question"
              }
            }
          }
        }
      }
    },
    "/api/v2/labs/{labId}/comments/{commentId}": {
      "delete": {
        "operationId": "delete_comment",
        "summary": "Delete comment",
        "description": "Deletes a comment owned by the current learner. A top-level deletion also removes its replies. SDK: `labs.deleteComment()`.",
        "tags": [
          "Labs"
        ],
        "x-sdk-method": "labs.deleteComment()",
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteCommentResponse"
                },
                "example": {
                  "ok": true,
                  "deletedCount": 1
                }
              }
            }
          },
          "400": {
            "description": "Invalid learner header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Organization API key required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lab or owned comment not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Discussion write limit reached. Read the Retry-After header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Other API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "labId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "commentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-cybr-learner-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            },
            "description": "Learner ID from the server session."
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "OrganizationKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "retryAfter": {
            "type": "number"
          },
          "activeCount": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "message"
        ]
      },
      "ResourceLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "const": "link",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "title",
          "url"
        ]
      },
      "GuideQuestion": {
        "type": "object",
        "properties": {
          "type": {
            "enum": [
              "text",
              "true_false"
            ]
          },
          "text": {
            "type": "string"
          },
          "hint": {
            "type": "string"
          },
          "placeholder": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "text"
        ]
      },
      "GuideTask": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "question": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/GuideQuestion"
              },
              {
                "type": "null"
              }
            ]
          },
          "flag": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "title",
          "body",
          "question",
          "flag"
        ]
      },
      "Guide": {
        "type": "object",
        "properties": {
          "version": {
            "const": 1,
            "type": "integer"
          },
          "objectives": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scenario": {
            "type": "string"
          },
          "tasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GuideTask"
            }
          },
          "completion": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "body": {
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "body"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "version",
          "objectives",
          "scenario",
          "tasks",
          "completion"
        ]
      },
      "Diagram": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "image",
              "html"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "kind",
          "url"
        ]
      },
      "Video": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "provider": {
            "enum": [
              "vimeo",
              "youtube"
            ]
          },
          "videoId": {
            "type": "string"
          },
          "hash": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "startSeconds": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "provider",
          "videoId"
        ]
      },
      "Writeup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "article",
              "video"
            ]
          }
        },
        "required": [
          "id",
          "kind",
          "title",
          "author",
          "url"
        ]
      },
      "Lab": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "provider": {
            "enum": [
              "aws",
              "azure"
            ]
          },
          "timeLimit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "estimatedLaunchSeconds": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "ctf": {
            "type": "boolean"
          },
          "free": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "hasGuide": {
            "type": "boolean"
          },
          "hasResources": {
            "type": "boolean"
          },
          "hasVideos": {
            "type": "boolean"
          },
          "hasWriteups": {
            "type": "boolean"
          },
          "webTerminal": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "description",
          "provider",
          "timeLimit",
          "estimatedLaunchSeconds",
          "ctf",
          "free",
          "createdAt",
          "updatedAt",
          "hasGuide",
          "hasResources",
          "hasVideos",
          "hasWriteups",
          "webTerminal"
        ]
      },
      "LabDetails": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "provider": {
            "enum": [
              "aws",
              "azure"
            ]
          },
          "timeLimit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "estimatedLaunchSeconds": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "ctf": {
            "type": "boolean"
          },
          "free": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "bannerUrl": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "webTerminal": {
            "type": "boolean"
          },
          "guide": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Guide"
              },
              {
                "type": "null"
              }
            ]
          },
          "resources": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ResourceLink"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "diagrams": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Diagram"
            }
          },
          "videos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Video"
            }
          },
          "writeups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Writeup"
            }
          },
          "completed": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "description",
          "provider",
          "timeLimit",
          "estimatedLaunchSeconds",
          "ctf",
          "free",
          "createdAt",
          "updatedAt",
          "bannerUrl",
          "webTerminal",
          "guide",
          "resources",
          "diagrams",
          "videos",
          "writeups",
          "completed"
        ]
      },
      "LaunchRequest": {
        "type": "object",
        "properties": {
          "labId": {
            "type": "string"
          },
          "learnerId": {
            "type": "string"
          },
          "membership": {
            "enum": [
              "free",
              "premium"
            ]
          },
          "sourceIp": {
            "type": "string",
            "description": "Learner public IP from trusted server request metadata. Unsupported values are ignored."
          }
        },
        "required": [
          "labId",
          "learnerId",
          "membership"
        ]
      },
      "LaunchResponse": {
        "type": "object",
        "properties": {
          "deploymentId": {
            "type": "string"
          },
          "version": {
            "const": "v2",
            "type": "string"
          }
        },
        "required": [
          "deploymentId",
          "version"
        ]
      },
      "DeploymentStatus": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "status": {
                "const": "loading",
                "type": "string"
              }
            },
            "required": [
              "status"
            ]
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "const": "failed",
                "type": "string"
              }
            },
            "required": [
              "status"
            ]
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "const": "complete",
                "type": "string"
              },
              "outputs": {
                "type": "object",
                "additionalProperties": true
              }
            },
            "required": [
              "status",
              "outputs"
            ]
          }
        ]
      },
      "DeploymentRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "deploymentId": {
            "type": "string"
          },
          "action": {
            "enum": [
              "apply",
              "destroy",
              "clean"
            ]
          },
          "status": {
            "enum": [
              "queued",
              "running",
              "completed",
              "errored"
            ]
          },
          "exitCode": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "outputs": {
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": true
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "startedAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "completedAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "deploymentId",
          "action",
          "status",
          "exitCode",
          "outputs",
          "error",
          "startedAt",
          "completedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "DestroyResponse": {
        "type": "object",
        "properties": {
          "deploymentId": {
            "type": "string"
          }
        },
        "required": [
          "deploymentId"
        ]
      },
      "TerminalSession": {
        "type": "object",
        "properties": {
          "wsUrl": {
            "type": "string",
            "format": "uri"
          },
          "protocols": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Deadline for connection authorization. It is not the shell lifetime or deployment deadline."
          }
        },
        "required": [
          "wsUrl",
          "expiresAt"
        ]
      },
      "FlagRequest": {
        "type": "object",
        "properties": {
          "learnerId": {
            "type": "string"
          },
          "flag": {
            "type": "string"
          }
        },
        "required": [
          "learnerId",
          "flag"
        ]
      },
      "FlagResponse": {
        "type": "object",
        "properties": {
          "message": {
            "enum": [
              "CORRECT_FLAG",
              "INCORRECT_FLAG",
              "NOT_CTF"
            ]
          }
        },
        "required": [
          "message"
        ]
      },
      "AnswerRequest": {
        "type": "object",
        "properties": {
          "taskId": {
            "type": "string"
          },
          "answer": {
            "type": [
              "string",
              "boolean"
            ]
          },
          "learnerId": {
            "type": "string"
          }
        },
        "required": [
          "taskId",
          "answer"
        ]
      },
      "AnswerResponse": {
        "type": "object",
        "properties": {
          "message": {
            "enum": [
              "CORRECT_ANSWER",
              "INCORRECT_ANSWER",
              "NO_QUESTION"
            ]
          }
        },
        "required": [
          "message"
        ]
      },
      "CompletionRequest": {
        "type": "object",
        "properties": {
          "learnerId": {
            "type": "string"
          }
        },
        "required": [
          "learnerId"
        ]
      },
      "CompletionResponse": {
        "type": "object",
        "properties": {
          "message": {
            "const": "COMPLETED",
            "type": "string"
          }
        },
        "required": [
          "message"
        ]
      },
      "Comment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "authorName": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "ownedByViewer": {
            "type": "boolean"
          },
          "deleted": {
            "type": "boolean"
          },
          "replies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            }
          }
        },
        "required": [
          "id",
          "authorName",
          "body",
          "createdAt",
          "ownedByViewer",
          "deleted",
          "replies"
        ]
      },
      "CommentsPage": {
        "type": "object",
        "properties": {
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            }
          },
          "nextCursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "totalCount": {
            "type": "integer"
          }
        },
        "required": [
          "comments",
          "nextCursor",
          "totalCount"
        ]
      },
      "CreateCommentRequest": {
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          },
          "displayName": {
            "type": "string"
          },
          "parentId": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "body"
        ]
      },
      "DeleteCommentResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true,
            "type": "boolean"
          },
          "deletedCount": {
            "type": "integer"
          }
        },
        "required": [
          "ok",
          "deletedCount"
        ]
      }
    }
  }
}
