openapi: 3.1.0
info:
  title: LightOn API
  version: 3.15.0 (v1)
  description: LightOn gives you an API to search, parse, and ingest documents at
    scale. Build knowledge-retrieval pipelines without managing vector databases or
    OCR models.
paths:
  /api/v3/ask:
    post:
      operationId: api_v3_ask_create
      description: |-
        Retrieval-augmented generation: searches your indexed corpus, then generates
        an LLM answer grounded in the retrieved passages.

        **Modes:**
        - `stream=false` (default): returns a single JSON response with `results` and `answer`.
        - `stream=true`: returns Server-Sent Events — `event: sources` (retrieved chunks),
          `event: token` (answer tokens), `event: done` (stream complete),
          or `event: error` (generation failure).

        **Model:** omit `model` to use the default model configured for your organization.
        Pass `model=alfred-ft5` for the lighter, faster LightOn fine-tune, or
        `model=mistral-large-latest` for the flagship general-purpose model.
        Company-specific custom models (`custom-{company_id}-{uuid}`) are also accepted.
        Any other value is rejected.

        **Structured output:** pass `response_format` with a JSON Schema object to constrain
        the LLM answer to valid JSON matching your schema. The schema must have
        `type: "object"` and `properties`. When set, the `answer` field contains a
        JSON string conforming to the schema. Works with both sync and streaming modes.
        Omit for free-text answers (default).

        **Relevance scoring:** relevance scoring always runs in `scoring_and_filtering`
        mode — candidates are scored for relevance and only those above the quality
        threshold are used as context. `score` equals the relevance score
        (`scores.relevance`, 0–1). Results are returned in descending order of `score`.
        If the scoring model is temporarily unavailable, `score` falls back to the
        combined retrieval score (higher is better, no fixed upper bound) and
        `scores.relevance` is null.

        **Scoping:** same rules as `/api/v3/search` — use `workspace_id` and/or `tag_id`
        to narrow results, or `file_id` to target specific files. `file_id` cannot be
        combined with `workspace_id` or `tag_id`.

        **Facet filtering:** use `content_type` and `attribute` to narrow results by facet
        metadata. Content type uses colon-separated paths (e.g. `legal:contract:nda`).
        **Repeated `attribute` entries are ANDed; values inside one entry are ORed with
        `|` (pipe, recommended).** Example: `attribute=fiscal_year:2024|2025&attribute=status:active`
        → (fiscal_year 2024 OR 2025) AND (status active). Supports operators (`>`, `>=`,
        `<`, `<=`), prefix (`name:prefix*`), smart dates, and content-type scoping.

        If the reranker is temporarily unavailable, results are returned in retrieval
        order and each result item includes a `warnings` array. Each warning has a
        `code` matching the degraded `scores` key (e.g. `relevance`) and a `reason`
        classifying the failure: `model_not_found`, `timeout`, `service_error`, or
        `unknown`. The `warnings` key is absent from result items when all pipeline
        steps succeed.

        Billing: 1 search-with-generation credit per request.
      summary: Ask a question over your documents
      tags:
      - Ask
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AskRequest'
            examples:
              DefaultModel—ScopedToWorkspace:
                value:
                  query: How are JWT tokens signed?
                  max_results: 5
                  workspace_id:
                  - 42
                summary: Default model — scoped to workspace
                description: Ask a question within a specific workspace using the
                  default model.
              AlternateModel—ScopedToFiles:
                value:
                  query: What is the quarterly revenue forecast?
                  max_results: 3
                  file_id:
                  - 101
                  - 102
                  model: alfred-ft5
                summary: Alternate model — scoped to files
                description: Ask using the lighter alfred-ft5 model, targeting specific
                  files.
              StreamingMode:
                value:
                  query: Summarize the onboarding process
                  stream: true
                summary: Streaming mode
                description: Stream the answer as Server-Sent Events.
              StructuredOutput—JSONSchema:
                value:
                  query: What are the key findings?
                  max_results: 5
                  workspace_id:
                  - 42
                  response_format:
                    type: object
                    properties:
                      findings:
                        type: array
                        items:
                          type: string
                      confidence:
                        type: number
                    required:
                    - findings
                    - confidence
                summary: Structured output — JSON schema
                description: Constrain the answer to match a JSON schema.
              Facet—ContentTypeFilter:
                value:
                  query: What are the indemnification terms?
                  content_type:
                  - legal:contract
                  max_results: 5
                summary: Facet — content type filter
                description: Ask only over documents classified as legal contracts.
              Facet—AttributeFilter:
                value:
                  query: What are the compliance requirements?
                  workspace_id:
                  - 42
                  content_type:
                  - legal
                  attribute:
                  - jurisdiction:FR
                  - effective_date:>2024-01-01
                summary: Facet — attribute filter
                description: Ask over documents with specific attribute values, combined
                  with workspace scoping.
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/AskRequest'
            examples:
              DefaultModel—ScopedToWorkspace:
                value:
                  query: How are JWT tokens signed?
                  max_results: 5
                  workspace_id:
                  - 42
                summary: Default model — scoped to workspace
                description: Ask a question within a specific workspace using the
                  default model.
              AlternateModel—ScopedToFiles:
                value:
                  query: What is the quarterly revenue forecast?
                  max_results: 3
                  file_id:
                  - 101
                  - 102
                  model: alfred-ft5
                summary: Alternate model — scoped to files
                description: Ask using the lighter alfred-ft5 model, targeting specific
                  files.
              StreamingMode:
                value:
                  query: Summarize the onboarding process
                  stream: true
                summary: Streaming mode
                description: Stream the answer as Server-Sent Events.
              StructuredOutput—JSONSchema:
                value:
                  query: What are the key findings?
                  max_results: 5
                  workspace_id:
                  - 42
                  response_format:
                    type: object
                    properties:
                      findings:
                        type: array
                        items:
                          type: string
                      confidence:
                        type: number
                    required:
                    - findings
                    - confidence
                summary: Structured output — JSON schema
                description: Constrain the answer to match a JSON schema.
              Facet—ContentTypeFilter:
                value:
                  query: What are the indemnification terms?
                  content_type:
                  - legal:contract
                  max_results: 5
                summary: Facet — content type filter
                description: Ask only over documents classified as legal contracts.
              Facet—AttributeFilter:
                value:
                  query: What are the compliance requirements?
                  workspace_id:
                  - 42
                  content_type:
                  - legal
                  attribute:
                  - jurisdiction:FR
                  - effective_date:>2024-01-01
                summary: Facet — attribute filter
                description: Ask over documents with specific attribute values, combined
                  with workspace scoping.
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/AskRequest'
            examples:
              DefaultModel—ScopedToWorkspace:
                value:
                  query: How are JWT tokens signed?
                  max_results: 5
                  workspace_id:
                  - 42
                summary: Default model — scoped to workspace
                description: Ask a question within a specific workspace using the
                  default model.
              AlternateModel—ScopedToFiles:
                value:
                  query: What is the quarterly revenue forecast?
                  max_results: 3
                  file_id:
                  - 101
                  - 102
                  model: alfred-ft5
                summary: Alternate model — scoped to files
                description: Ask using the lighter alfred-ft5 model, targeting specific
                  files.
              StreamingMode:
                value:
                  query: Summarize the onboarding process
                  stream: true
                summary: Streaming mode
                description: Stream the answer as Server-Sent Events.
              StructuredOutput—JSONSchema:
                value:
                  query: What are the key findings?
                  max_results: 5
                  workspace_id:
                  - 42
                  response_format:
                    type: object
                    properties:
                      findings:
                        type: array
                        items:
                          type: string
                      confidence:
                        type: number
                    required:
                    - findings
                    - confidence
                summary: Structured output — JSON schema
                description: Constrain the answer to match a JSON schema.
              Facet—ContentTypeFilter:
                value:
                  query: What are the indemnification terms?
                  content_type:
                  - legal:contract
                  max_results: 5
                summary: Facet — content type filter
                description: Ask only over documents classified as legal contracts.
              Facet—AttributeFilter:
                value:
                  query: What are the compliance requirements?
                  workspace_id:
                  - 42
                  content_type:
                  - legal
                  attribute:
                  - jurisdiction:FR
                  - effective_date:>2024-01-01
                summary: Facet — attribute filter
                description: Ask over documents with specific attribute values, combined
                  with workspace scoping.
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AskResponse'
              examples:
                SynchronousAnswer—WithFacetData:
                  value:
                    results:
                    - chunk_id: 550e8400-e29b-41d4-a716-446655440000
                      content: JWT tokens are signed using RS256 and expire after
                        1 hour.
                      score: 0.95
                      scores:
                        text: 0.91
                        vision: null
                        keyword: 0.43
                        multivector: 0.78
                        relevance: 0.95
                      source:
                        file_id: 512
                        filename: auth-system.pdf
                        title: Authentication System Design
                        mime_type: pdf
                        size_bytes: 482113
                        page_start: 3
                        page_end: 4
                        total_pages: 12
                        tags:
                        - id: 7
                          name: security
                        content_types:
                        - path: engineering:security
                          label: Security
                          attribute_values:
                            topic:
                              value: authentication
                              type: text
                        external_metadata: null
                      workspace:
                        id: 42
                        name: Engineering Docs
                    answer: Based on the authentication system design document, JWT
                      tokens are signed using RS256 and have a 1-hour expiration (auth-system.pdf,
                      page 3).
                  summary: Synchronous answer — with facet data
                  description: Complete answer with source chunks. Source includes
                    content_types with attribute values when documents have facet
                    classifications.
                SynchronousAnswer—RerankerUnavailable:
                  value:
                    results:
                    - chunk_id: 550e8400-e29b-41d4-a716-446655440000
                      content: JWT tokens are signed using RS256 and expire after
                        1 hour.
                      score: 1.65
                      scores:
                        text: 0.91
                        vision: null
                        keyword: 0.43
                        multivector: 0.78
                        relevance: null
                      source:
                        file_id: 512
                        filename: auth-system.pdf
                        title: Authentication System Design
                        mime_type: pdf
                        size_bytes: 482113
                        page_start: 3
                        page_end: 4
                        total_pages: 12
                        tags: []
                        content_types: []
                        external_metadata: null
                      workspace:
                        id: 42
                        name: Engineering Docs
                      warnings:
                      - code: relevance
                        reason: model_not_found
                    answer: 'Based on the available documents, JWT tokens are signed
                      using RS256 and have a 1-hour expiration. Note: relevance scoring
                      was unavailable for this request.'
                  summary: Synchronous answer — reranker unavailable
                  description: Reranker degraded; each result item carries a warnings
                    array. score falls back to the combined retrieval score (no fixed
                    upper bound) and scores.relevance is null. The warnings key is
                    absent when healthy.
                SynchronousAnswer—NoFacets:
                  value:
                    results:
                    - chunk_id: 550e8400-e29b-41d4-a716-446655440000
                      content: JWT tokens are signed using RS256 and expire after
                        1 hour.
                      score: 0.95
                      scores:
                        text: 0.91
                        vision: null
                        keyword: 0.43
                        multivector: 0.78
                        relevance: 0.95
                      source:
                        file_id: 512
                        filename: auth-system.pdf
                        title: Authentication System Design
                        mime_type: pdf
                        size_bytes: 482113
                        page_start: 3
                        page_end: 4
                        total_pages: 12
                        tags:
                        - id: 7
                          name: security
                        content_types: []
                        external_metadata: null
                      workspace:
                        id: 42
                        name: Engineering Docs
                    answer: Based on the authentication system design document, JWT
                      tokens are signed using RS256 and have a 1-hour expiration (auth-system.pdf,
                      page 3).
                  summary: Synchronous answer — no facets
                  description: Answer with source chunks without facet content type
                    data.
          description: |-
            Synchronous mode (`stream=false`): complete answer with sources.

            Streaming mode (`stream=true`): Server-Sent Events with `event: sources`, `event: token`, and `event: done` (or `event: error`).
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                BadRequest:
                  value:
                    id: null
                    code: 400
                    error: bad_request
                    detail: The request body could not be parsed as valid JSON.
                    doc_url: https://developers.lighton.ai/errors#bad_request
                  summary: Bad Request
          description: Request body is not valid JSON
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InsufficientPermissions:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: None of the provided filters resolve to authorized resources.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
                  summary: Insufficient permissions
          description: API key has no authorized resources matching the provided filters.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                ModelUnavailableOnBackend:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: Model 'mistral-large-latest' not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Model unavailable on backend
          description: An explicitly requested model (`mistral-large-latest` or `alfred-ft5`)
            is not currently available on the backend. (An unsupported `model` value
            is rejected earlier with a 422.)
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError—ScopingConflict:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      file_id:
                      - error: invalid_combination
                        detail: file_id cannot be combined with workspace_id or tag_id.
                  summary: Validation error — scoping conflict
                ValidationError—InvalidResponseFormat:
                  value:
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    fields:
                      response_format:
                      - error: invalid
                        detail: response_format type must be 'object'
                  summary: Validation error — invalid response_format
                ValidationError—UnsupportedModel:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      model:
                      - error: invalid_choice
                        detail: '"gpt-4" is not a valid choice.'
                  summary: Validation error — unsupported model
          description: Field validation failure.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InternalServerError:
                  value:
                    id: null
                    code: 500
                    error: internal_server_error
                    detail: An unexpected error occurred. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#internal_server_error
                  summary: Internal Server Error
          description: An unexpected error occurred
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
        '504':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                ModelTimeout:
                  value:
                    id: null
                    code: 504
                    error: model_timeout
                    detail: The model did not respond in time. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#model_timeout
                  summary: Model timeout
          description: Model timeout.
  /api/v3/billing/budget:
    get:
      operationId: api_v3_billing_budget_retrieve
      description: Return the company's monthly budget configuration, current spend,
        and alert thresholds.
      summary: Get company budget
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BudgetResponse'
          description: ''
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    put:
      operationId: api_v3_billing_budget_update
      description: Set or update the company's monthly spend budget. Requires CompanyAdmin
        role. Creates the budget on first call; updates it on subsequent calls.
      summary: Create or update company budget
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BudgetResponse'
          description: ''
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BudgetResponse'
          description: ''
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    delete:
      operationId: api_v3_billing_budget_destroy
      description: Delete the company's budget and all associated alerts. Requires
        CompanyAdmin role.
      summary: Delete company budget
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '204':
          description: No response body
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/billing/budget/alerts:
    get:
      operationId: api_v3_billing_budget_alerts_retrieve
      description: Return all alert thresholds for the company's budget.
      summary: List budget alerts
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '200':
          description: No response body
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    post:
      operationId: api_v3_billing_budget_alerts_create
      description: Add an alert threshold to the company's budget.
      summary: Create budget alert
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '200':
          description: No response body
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    patch:
      operationId: api_v3_billing_budget_alerts_partial_update
      description: Enable or disable all alert thresholds for the company's budget
        in a single operation.
      summary: Toggle all budget alerts
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '200':
          description: No response body
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/billing/budget/alerts/{id}:
    patch:
      operationId: api_v3_billing_budget_alerts_partial_update_2
      description: Update an existing alert threshold.
      summary: Update budget alert
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        required: true
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '200':
          description: No response body
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    delete:
      operationId: api_v3_billing_budget_alerts_destroy
      description: Delete an alert threshold.
      summary: Delete budget alert
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        required: true
      tags:
      - Budget
      security:
      - bearerAuth: []
      responses:
        '204':
          description: No response body
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/extract:
    post:
      operationId: api_v3_extract_create
      description: |-
        Pull specific fields from a document into a typed schema.

        Accepts exactly one of: a **file upload** (multipart/form-data), a **document URL** (JSON body), or a **`file_id`** referencing an already-ingested document (from `POST /v3/files`), plus a **JSON Schema** (the `schema` field) describing what to extract.

        ### Sync mode (default)
        Blocks until extraction completes and returns **200** with the full result.

        ```bash
        curl -X POST https://api.lighton.ai/api/v3/extract \
          -H 'Authorization: Bearer $TOKEN' \
          -F file=@invoice.pdf \
          -F 'schema={"type":"object","properties":{"invoice_number":{"type":"string"}}}'
        ```

        ### Async mode (`options.async = true`)
        Returns **202** immediately with an `ext_<token>` job id. Poll `GET /api/v3/extract/{id}` with that same id until `status` is `completed` or `failed`.

        ```bash
        curl -X POST https://api.lighton.ai/api/v3/extract \
          -H 'Authorization: Bearer $TOKEN' \
          -H 'Content-Type: application/json' \
          -d '{"document": "https://example.com/report.pdf", "schema": {"type": "object", "properties": {"title": {"type": "string"}}}, "options": {"async": true}}'
        ```

        For multipart uploads, pass `options` as a JSON-encoded form field: `-F 'options={"async":true}'`.

        **Supported file types:** `.pdf`, `.png`, `.jpg`, `.jpeg`, `.pptx`, `.ppt`, `.odp`, `.docx`, `.odt`, `.doc`, `.html`

        **Sync limits:** 20 MB file size, 15 pages.

        **Async limits:** 100 MB file size, 1000 pages.
      summary: Extract structured data from a document
      tags:
      - Extract
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ExtractRequest'
            examples:
              ExtractViaFileUpload(sync):
                value:
                  file: (binary)
                  schema:
                    type: object
                    properties:
                      invoice_number:
                        type: string
                summary: Extract via file upload (sync)
                description: Upload a PDF and provide a JSON Schema to extract specific
                  fields.
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ExtractRequest'
          application/json:
            schema:
              $ref: '#/components/schemas/ExtractRequest'
            examples:
              ExtractViaDocumentURL(sync):
                value:
                  document: https://example.com/invoice.pdf
                  schema:
                    type: object
                    properties:
                      invoice_number:
                        type: string
                        description: The invoice reference number
                      total:
                        type: number
                        description: The total amount due
                summary: Extract via document URL (sync)
                description: Provide a publicly accessible document URL and a JSON
                  Schema.
              ExtractAsynchronously:
                value:
                  document: https://example.com/large-report.pdf
                  schema:
                    type: object
                    properties:
                      title:
                        type: string
                  options:
                    async: true
                summary: Extract asynchronously
                description: Same as above with options.async=true. Returns 202 with
                  a job ID.
              ExtractViaFileId(sync):
                value:
                  file_id: 42
                  schema:
                    type: object
                    properties:
                      invoice_number:
                        type: string
                      total:
                        type: number
                summary: Extract via file_id (sync)
                description: Reference an already-ingested document (from POST /v3/files)
                  by id.
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExtractJobResponse'
              examples:
                SyncExtractionResponse:
                  value:
                    id: ext_0196e4b2a3c14d5e8f7a9b2c1d0e3f4a
                    status: completed
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: '2026-03-31T10:00:04+00:00'
                    processing_time_ms: 3200
                    document:
                      filename: invoice.pdf
                      page_count: 3
                      file_size_bytes: 245120
                      mime_type: application/pdf
                    result:
                      data:
                      - invoice_number: INV-2026-001
                        total: null
                        line_items: null
                      - invoice_number: null
                        total: 1250.0
                        line_items:
                        - description: Widget A
                          quantity: 10
                          unit_price: 50.0
                        - description: Widget B
                          quantity: 5
                          unit_price: 150.0
                      - invoice_number: null
                        total: null
                        line_items: null
                      pagination:
                        page: 1
                        page_size: 15
                        total_items: 3
                        total_pages: 1
                        has_next: false
                        has_prev: false
                    usage:
                      pages_processed: 3
                    progress:
                      percentage: 100
                      pages_processed: 3
                  summary: Sync extraction response
          description: Extraction completed (sync mode).
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExtractJobResponse'
              examples:
                AsyncAcceptedResponse:
                  value:
                    id: ext_0196e4b2a3c14d5e8f7a9b2c1d0e3f4a
                    status: pending
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: null
                    processing_time_ms: null
                    document:
                      filename: large-report.pdf
                      page_count: null
                      file_size_bytes: 5242880
                      mime_type: application/pdf
                    result: null
                    usage: null
                    progress: null
                  summary: Async accepted response
          description: Extraction accepted (async mode). Poll GET /v3/extract/{id}
            for status.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                MissingSource:
                  value:
                    id: null
                    code: 400
                    error: missing_input
                    detail: A file upload, document URL, or file_id is required.
                    doc_url: https://developers.lighton.ai/errors#missing_input
                  summary: Missing source
                AmbiguousSource:
                  value:
                    id: null
                    code: 400
                    error: ambiguous_input
                    detail: 'Provide exactly one of: file upload, document URL, or
                      file_id.'
                    doc_url: https://developers.lighton.ai/errors#ambiguous_input
                  summary: Ambiguous source
                PageLimitExceeded:
                  value:
                    id: null
                    code: 400
                    error: max_pages_exceeded
                    detail: Document has 1200 pages, exceeding the async limit of
                      1000 pages.
                    doc_url: https://developers.lighton.ai/errors#max_pages_exceeded
                  summary: Page limit exceeded
          description: Bad request — missing/ambiguous source, unsupported format,
            or page limit exceeded.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                DocumentNotFoundOrUnauthorized:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: Document not found or access denied.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Document not found or unauthorized
                DocumentFileMissing:
                  value:
                    id: null
                    code: 404
                    error: document_file_not_found
                    detail: The document's stored file could not be found.
                    doc_url: https://developers.lighton.ai/errors#document_file_not_found
                  summary: Document file missing
          description: '`file_id` does not exist, is not authorized for the requesting
            user, or its stored file is missing.'
        '413':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                PayloadTooLarge:
                  value:
                    id: null
                    code: 413
                    error: payload_too_large
                    detail: File size (157286400 bytes) exceeds the 100MB async limit.
                    doc_url: https://developers.lighton.ai/errors/payload_too_large
                  summary: Payload too large
          description: File exceeds the size limit (20 MB sync, 100 MB async).
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                MalformedJSONSchema:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: The provided JSON Schema is malformed.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      schema:
                      - error: invalid
                        detail: 'JSON Schema is not valid: missing ''type'' keyword.'
                  summary: Malformed JSON Schema
          description: JSON Schema is malformed, uses unsupported features, or exceeds
            limits.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/extract/{job_id}:
    get:
      operationId: api_v3_extract_retrieve
      description: |-
        Poll for the status and result of an async extract job submitted via `POST /api/v3/extract` with `options.async=true`. Returns the same envelope shape as the synchronous extract endpoint once `status` is `completed`.

        ```bash
        curl https://api.lighton.ai/api/v3/extract/ext_0196e4b2a3c14d5e \
          -H 'Authorization: Bearer $TOKEN'
        ```

        **Pagination:** when completed, `result.data` is paginated with a fixed page size of 15. Use the `page` query param (1-based) to navigate; `result.pagination` reports `total_items`, `total_pages`, `has_next`, `has_prev`.

        **Recommended polling cadence:** 1s for the first 10s, then 5s, capped at 30s. Stop polling once `status` is in `{completed, failed}`.
      summary: Get the status and result of an async extract job
      parameters:
      - in: path
        name: job_id
        schema:
          type: string
        required: true
      - in: query
        name: page
        schema:
          type: integer
          default: 1
        description: 1-based page index for navigating `result.data`. Fixed page size
          of 15 items. An out-of-range page is rejected.
      tags:
      - Extract
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExtractJobResponse'
              examples:
                CompletedJob:
                  value:
                    id: ext_0196e4b2a3c14d5e8f7a9b2c1d0e3f4a
                    status: completed
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: '2026-03-31T10:00:04+00:00'
                    processing_time_ms: 3200
                    document:
                      filename: invoice.pdf
                      page_count: 3
                      file_size_bytes: 245120
                      mime_type: application/pdf
                    result:
                      data:
                      - invoice_number: INV-2026-001
                        total: null
                      - invoice_number: null
                        total: 1250.0
                      - invoice_number: null
                        total: null
                      pagination:
                        page: 1
                        page_size: 15
                        total_items: 3
                        total_pages: 1
                        has_next: false
                        has_prev: false
                    usage:
                      pages_processed: 3
                    progress:
                      percentage: 100
                      pages_processed: 3
                  summary: Completed job
                ProcessingJob:
                  value:
                    id: ext_0196e4b2a3c14d5e8f7a9b2c1d0e3f4d
                    status: processing
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: null
                    processing_time_ms: null
                    document:
                      filename: large-report.pdf
                      page_count: 450
                      file_size_bytes: 5242880
                      mime_type: application/pdf
                    result: null
                    usage: null
                    progress:
                      percentage: 27
                      pages_processed: 120
                  summary: Processing job
                  description: A worker is extracting page-by-page. `progress` is
                    the completion percentage [0, 100] so clients can show a determinate
                    progress bar. Keep polling.
                PendingJob:
                  value:
                    id: ext_0196e4b2a3c14d5e8f7a9b2c1d0e3f4b
                    status: pending
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: null
                    processing_time_ms: null
                    document:
                      filename: large-report.pdf
                      page_count: null
                      file_size_bytes: 5242880
                      mime_type: application/pdf
                    result: null
                    usage: null
                    progress: null
                  summary: Pending job
                FailedJob:
                  value:
                    id: ext_0196e4b2a3c14d5e8f7a9b2c1d0e3f4c
                    status: failed
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: '2026-03-31T10:00:05+00:00'
                    processing_time_ms: null
                    document:
                      filename: corrupted.pdf
                      page_count: null
                      file_size_bytes: 102400
                      mime_type: application/pdf
                    result: null
                    usage: null
                    progress: null
                  summary: Failed job
          description: Extract job status (pending, processing, completed, or failed).
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/parse:
    post:
      operationId: api_v3_parse_create
      description: |-
        Convert a document into readable, structured Markdown content.

        Accepts either a **file upload** (multipart/form-data) or a **document URL** (JSON body).

        ### Sync mode (default)
        Blocks until parsing completes and returns **200** with the full markdown result.

        ```bash
        curl -X POST https://api.lighton.ai/api/v3/parse \
          -H 'Authorization: Bearer $TOKEN' \
          -F file=@invoice.pdf
        ```

        ### Async mode (`options.async = true`)
        Returns **202** immediately with a `parse_<token>` job id. Poll `GET /api/v3/parse/{id}` with that same id until `status` is `completed` or `failed`.

        ```bash
        curl -X POST https://api.lighton.ai/api/v3/parse \
          -H 'Authorization: Bearer $TOKEN' \
          -H 'Content-Type: application/json' \
          -d '{"document": "https://example.com/report.pdf", "options": {"async": true}}'
        ```

        For multipart uploads, pass `options` as a JSON-encoded form field: `-F 'options={"async":true}'`.

        **Supported file types:** `.pdf`, `.png`, `.jpg`, `.jpeg`, `.pptx`, `.ppt`, `.odp`, `.docx`, `.odt`, `.doc`, `.html`

        **Sync limits:** 20 MB file size, 15 pages.

        **Async limits:** 100 MB file size, 1000 pages.
      summary: Parse a document to Markdown
      tags:
      - Parse
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ParseJsonRequest'
            examples:
              Sync—DocumentURL:
                value:
                  document: https://example.com/invoice.pdf
                summary: Sync — document URL
                description: Provide a publicly accessible document URL. Returns 200
                  with the markdown result.
              Async—DocumentURL:
                value:
                  document: https://example.com/report.pdf
                  options:
                    async: true
                summary: Async — document URL
                description: Async variant of the URL-based request. Set `options.async=true`
                  in the JSON body.
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ParseMultipartRequest'
            examples:
              Sync—FileUpload:
                value:
                  file: (binary)
                summary: Sync — file upload
                description: Upload a PDF directly for synchronous parsing. Returns
                  200 with the markdown result.
              Async—FileUpload:
                value:
                  file: (binary)
                  options: '{"async": true}'
                summary: Async — file upload
                description: Queue the document by setting `options.async=true`. For
                  multipart, pass `options` as a JSON-encoded form field. Response
                  is 202 with a `parse_<token>` job id to poll.
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ParseResponse'
              examples:
                Sync—Completed:
                  value:
                    id: parse_0196e4b2a3c14d5e8f7a9b2c1d0e3f4a
                    status: completed
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: '2026-03-31T10:00:03+00:00'
                    processing_time_ms: 2840
                    document:
                      filename: invoice.pdf
                      page_count: 3
                      file_size_bytes: 245120
                      mime_type: application/pdf
                    result:
                      pages:
                      - index: 1
                        markdown: |-
                          # Invoice

                          Invoice Number: INV-2026-001
                          Date: March 15, 2026
                      - index: 2
                        markdown: |-
                          ## Terms

                          Payment is due within 30 days...
                      - index: 3
                        markdown: |-
                          ## Appendix

                          Line items continued...
                    usage:
                      pages_processed: 3
                  summary: Sync — completed
                  description: Returned by the default (sync) path. Body contains
                    the full markdown result.
          description: Sync parse — document parsed successfully.
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ParseAsyncResponse'
              examples:
                Async—Accepted:
                  value:
                    id: parse_Kg
                    status: pending
                    created_at: '2026-03-31T10:00:00+00:00'
                  summary: Async — accepted
                  description: Returned when `options.async=true` is set. `id` is
                    the token to poll with.
          description: Async parse — job accepted. Poll `GET /api/v3/parse/{id}` with
            the returned `id` until `status` is `completed` or `failed`.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                PageLimitExceeded:
                  value:
                    id: null
                    code: 400
                    error: max_pages_exceeded
                    detail: Document has 1200 pages, exceeding the async limit of
                      1000 pages.
                    doc_url: https://developers.lighton.ai/errors#max_pages_exceeded
                  summary: Page limit exceeded
          description: Bad request — unsupported format, or page limit exceeded (15
            pages sync / 1000 pages async).
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                MissingDocument:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      document:
                      - error: required
                        detail: A file upload or document URL is required.
                  summary: Missing document
          description: Validation error — missing document, both a file and a URL
            provided, or an invalid document URL.
        '413':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                PayloadTooLarge:
                  value:
                    id: null
                    code: 413
                    error: payload_too_large
                    detail: File size (157286400 bytes) exceeds the 100MB async limit.
                    doc_url: https://developers.lighton.ai/errors/payload_too_large
                  summary: Payload too large
          description: File exceeds the size limit (20 MB sync / 100 MB async).
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/parse/{id}:
    get:
      operationId: api_v3_parse_retrieve
      description: |-
        Poll for the status and result of an async parse job submitted via `POST /api/v3/parse` with `options.async=true`. Returns the same envelope shape as the synchronous parse endpoint once `status` is `completed`.

        ```bash
        curl https://api.lighton.ai/api/v3/parse/parse_Kg \
          -H 'Authorization: Bearer $TOKEN'
        ```

        **Recommended polling cadence:** 1s for the first 10s, then 5s, capped at 30s. Stop polling once `status` is in `{completed, failed}`.
      summary: Get the status and result of an async parse job
      parameters:
      - in: path
        name: id
        schema:
          type: string
        description: Public parse job id (e.g. `parse_Kg`) returned by `POST /api/v3/parse`
          with `options.async=true`. Malformed or unknown tokens return 404.
        required: true
        examples:
          AsyncJobId:
            value: parse_Kg
            summary: Async job id
      tags:
      - Parse
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ParseJobStatus'
              examples:
                Pending—JustSubmitted:
                  value:
                    id: parse_Kg
                    status: pending
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: null
                    processing_time_ms: null
                    document:
                      filename: report.pdf
                      page_count: null
                      file_size_bytes: 245120
                      mime_type: application/pdf
                    result: null
                    usage: null
                    progress: null
                    error: null
                  summary: Pending — just submitted
                  description: Returned immediately after the 202; the job has not
                    been picked up yet.
                Processing—InFlight:
                  value:
                    id: parse_Kg
                    status: processing
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: null
                    processing_time_ms: null
                    document:
                      filename: report.pdf
                      page_count: null
                      file_size_bytes: 245120
                      mime_type: application/pdf
                    result: null
                    usage: null
                    progress:
                      percentage: 27
                      pages_processed: 120
                    error: null
                  summary: Processing — in flight
                  description: A worker has picked up the job. `progress` reports
                    pages parsed so far and the completion `percentage` [0, 100] so
                    clients can show a determinate progress bar. Keep polling.
                Completed—TerminalSuccess:
                  value:
                    id: parse_Kg
                    status: completed
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: '2026-03-31T10:00:18+00:00'
                    processing_time_ms: 18420
                    document:
                      filename: report.pdf
                      page_count: 3
                      file_size_bytes: 245120
                      mime_type: application/pdf
                    result:
                      pages:
                      - index: 1
                        markdown: |-
                          # Report

                          ...
                      - index: 2
                        markdown: |-
                          ## Section 2

                          ...
                      - index: 3
                        markdown: |-
                          ## Section 3

                          ...
                    usage:
                      pages_processed: 3
                    progress:
                      percentage: 100
                      pages_processed: 3
                    error: null
                  summary: Completed — terminal success
                  description: Terminal success. `result.pages` and `usage.pages_processed`
                    are populated; stop polling.
                Failed—TerminalFailure:
                  value:
                    id: parse_Kg
                    status: failed
                    created_at: '2026-03-31T10:00:00+00:00'
                    completed_at: '2026-03-31T10:00:08+00:00'
                    processing_time_ms: 5120
                    document:
                      filename: report.pdf
                      page_count: null
                      file_size_bytes: 245120
                      mime_type: application/pdf
                    result: null
                    usage: null
                    progress: null
                    error:
                      message: Parsing failed.
                  summary: Failed — terminal failure
                  description: Terminal failure. `error.message` carries the failure
                    reason; stop polling.
          description: Async parse job status and (once terminal) result. `status`
            is `pending`/`processing` while in flight, `completed` on success, `failed`
            on failure. The `result` and `usage` blocks are populated only on success;
            the `error` block is populated only on failure.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/preview:
    post:
      operationId: api_v3_preview_create
      description: |-
        Convert a document into a PDF suitable for inline preview.

        Accepts a **file upload** (multipart/form-data), a **document URL**, or a **file_id** referencing a document already ingested in the platform (JSON body). The conversion is synchronous — the PDF bytes are returned directly.

        **Supported file types:** `.pdf`, `.png`, `.jpg`, `.jpeg`, `.pptx`, `.ppt`, `.odp`, `.docx`, `.odt`, `.doc`, `.html`, `.xhtml`

        **Size limit:** 20 MB.
      summary: Render a document as PDF
      tags:
      - Parse
      requestBody:
        content:
          multipart/form-data:
            schema:
              multipart/form-data:
                type: object
                properties:
                  file:
                    type: string
                    format: binary
                    description: The document to convert.
              application/json:
                type: object
                properties:
                  document:
                    type: string
                    format: uri
                    description: Publicly accessible URL of the document to convert.
                  file_id:
                    type: integer
                    description: ID of a document already ingested in the platform.
                      Mutually exclusive with `document`.
            examples:
              RenderAPDFViaFileUpload:
                value:
                  file: (binary)
                summary: Render a PDF via file upload
                description: Upload a document file directly for synchronous PDF rendering.
          application/x-www-form-urlencoded:
            schema:
              multipart/form-data:
                type: object
                properties:
                  file:
                    type: string
                    format: binary
                    description: The document to convert.
              application/json:
                type: object
                properties:
                  document:
                    type: string
                    format: uri
                    description: Publicly accessible URL of the document to convert.
                  file_id:
                    type: integer
                    description: ID of a document already ingested in the platform.
                      Mutually exclusive with `document`.
          application/json:
            schema:
              multipart/form-data:
                type: object
                properties:
                  file:
                    type: string
                    format: binary
                    description: The document to convert.
              application/json:
                type: object
                properties:
                  document:
                    type: string
                    format: uri
                    description: Publicly accessible URL of the document to convert.
                  file_id:
                    type: integer
                    description: ID of a document already ingested in the platform.
                      Mutually exclusive with `document`.
            examples:
              RenderADocumentViaURL:
                value:
                  document: https://example.com/report.docx
                summary: Render a document via URL
                description: Provide a publicly accessible document URL.
              RenderAnIngestedDocumentByID:
                value:
                  file_id: 42
                summary: Render an ingested document by ID
                description: Reference a document already ingested in the platform.
      security:
      - bearerAuth: []
      responses:
        '200':
          description: PDF rendered successfully. Response body is the raw PDF bytes.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                UnsupportedFormat:
                  value:
                    id: null
                    code: 400
                    error: unsupported_format
                    detail: Unsupported document format.
                    doc_url: https://developers.lighton.ai/errors#unsupported_format
                  summary: Unsupported format
          description: Bad request — missing document, unsupported format, or invalid
            URL.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '413':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                PayloadTooLarge:
                  value:
                    id: null
                    code: 413
                    error: payload_too_large
                    detail: File exceeds the 20 MB size limit.
                    doc_url: https://developers.lighton.ai/errors#payload_too_large
                  summary: Payload too large
          description: File exceeds the 20 MB size limit.
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                ConversionFailed:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: Conversion failed — corrupt file or LibreOffice error.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                  summary: Conversion failed
          description: Conversion failed — corrupt file or LibreOffice error.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/search:
    post:
      operationId: api_v3_search_create
      description: |-
        Embedding → hybrid vector search → optional reranking, returning ranked chunks
        with provenance. No LLM generation is performed.

        Billing: 1 retrieval credit per request.

        **Relevance scoring (`relevance_scoring`):** controls the relevance scoring stage.
        - `scoring_and_filtering` (default): Score candidates for relevance and only
          return those above the quality threshold.
        - `scoring_only`: Score every candidate for relevance but return them all, even
          low-scoring ones. Useful for building your own filtering logic.
        - `none`: Skip the relevance scoring step and return all candidates unfiltered.
          Fastest option, useful when you handle scoring yourself.

        Omit `relevance_scoring` for the default; send `none` to skip scoring.
        `skip_rerank` is deprecated — `true` maps to `none`, `false` to `scoring_and_filtering`.

        **Result ordering:** results are returned in descending order of `score`.
        With `scoring_and_filtering` or `scoring_only`, `score` equals the relevance
        score (`scores.relevance`, 0–1). With `none`, `score` is the combined retrieval
        score (higher is better, no fixed upper bound).

        If the scoring model is temporarily unavailable, results are returned in
        retrieval order and a `warnings` array is included. Each warning has a `code`
        matching the degraded `scores` key (e.g. `relevance`) and a `reason` classifying the
        failure: `model_not_found`, `timeout`, `service_error`, or `unknown`.
        The `warnings` key is absent when all pipeline steps succeed.

        **Scoping:** use `workspace_id` and/or `tag_id` to narrow results, or `file_id`
        to target specific files. `file_id` cannot be combined with `workspace_id` or
        `tag_id`. Filters that resolve to no authorized resources are rejected.
        When no filters are provided, search runs across all documents authorized for the
        API key.

        **Facet filtering:** use `content_type` and `attribute` to narrow results by facet
        metadata. Content type uses colon-separated paths (e.g. `legal:contract:nda`).
        **Repeated `attribute` entries are ANDed; values inside one entry are ORed with
        `|` (pipe, recommended).** Example: `attribute=fiscal_year:2024|2025&attribute=status:active`
        → (fiscal_year 2024 OR 2025) AND (status active). Supports operators (`>`, `>=`,
        `<`, `<=`), prefix (`name:prefix*`), smart dates, and content-type scoping.

        **Modes:**
        - `text` (default): hybrid text search
        - `vision`: VLM-embedded page image search

        **Images:** set `include_image=true` to receive a base64-encoded page image with
        each result. In text mode the image is fetched from the VisionChunk covering the
        chunk's start page (empty string if no vision index exists for that page).

        **Bounding boxes (PDF only):** set `include_bboxes=true` to append a `bboxes` array to each
        result, giving the merged rectangles of the chunk's text on the source PDF (raw
        PDF points, top-left origin with y extending downward) so you can overlay highlights without re-locating
        the chunk. One rectangle per logical group; a chunk spanning two pages produces at
        least one rectangle per page. Available for PDF documents in text mode only — returns an
        empty list for non-PDF, vision-mode, or pre-v2.2.1 chunks. When `include_bboxes=false`
        (default) the `bboxes` key is omitted.
      summary: Search document chunks
      tags:
      - Search
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
            examples:
              TextSearch—ScopedToWorkspace:
                value:
                  query: authentication system JWT tokens
                  max_results: 5
                  workspace_id:
                  - 42
                summary: Text search — scoped to workspace
                description: Search within a specific workspace using hybrid text
                  search with reranking.
              TextSearch—ScopedToFiles:
                value:
                  query: quarterly revenue forecast
                  max_results: 3
                  file_id:
                  - 101
                  - 102
                summary: Text search — scoped to files
                description: Search specific files only.
              TextSearch—AcrossAllDocuments:
                value:
                  query: onboarding process
                  max_results: 10
                summary: Text search — across all documents
                description: Search across all documents the API key has access to.
              RawRetrieval—SkipScoring:
                value:
                  query: incident response playbook
                  max_results: 10
                  relevance_scoring: none
                summary: Raw retrieval — skip scoring
                description: Bypass relevance scoring for lower latency (relevance_scoring="none").
                  scores.relevance will be null.
              TextSearch—WithBoundingBoxes:
                value:
                  query: authentication system JWT tokens
                  max_results: 5
                  include_bboxes: true
                summary: Text search — with bounding boxes
                description: Append merged PDF bounding boxes to each result for overlaying
                  chunk highlights.
              Facet—ContentTypeFilter:
                value:
                  query: indemnification clause
                  content_type:
                  - legal:contract
                  max_results: 5
                summary: Facet — content type filter
                description: Search only documents classified as legal contracts.
              Facet—AttributeFilter:
                value:
                  query: compliance requirements
                  workspace_id:
                  - 42
                  content_type:
                  - legal
                  attribute:
                  - jurisdiction:FR
                  - effective_date:>2024-01-01
                summary: Facet — attribute filter
                description: Search documents with specific attribute values, combined
                  with workspace scoping.
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SearchRequest'
            examples:
              TextSearch—ScopedToWorkspace:
                value:
                  query: authentication system JWT tokens
                  max_results: 5
                  workspace_id:
                  - 42
                summary: Text search — scoped to workspace
                description: Search within a specific workspace using hybrid text
                  search with reranking.
              TextSearch—ScopedToFiles:
                value:
                  query: quarterly revenue forecast
                  max_results: 3
                  file_id:
                  - 101
                  - 102
                summary: Text search — scoped to files
                description: Search specific files only.
              TextSearch—AcrossAllDocuments:
                value:
                  query: onboarding process
                  max_results: 10
                summary: Text search — across all documents
                description: Search across all documents the API key has access to.
              RawRetrieval—SkipScoring:
                value:
                  query: incident response playbook
                  max_results: 10
                  relevance_scoring: none
                summary: Raw retrieval — skip scoring
                description: Bypass relevance scoring for lower latency (relevance_scoring="none").
                  scores.relevance will be null.
              TextSearch—WithBoundingBoxes:
                value:
                  query: authentication system JWT tokens
                  max_results: 5
                  include_bboxes: true
                summary: Text search — with bounding boxes
                description: Append merged PDF bounding boxes to each result for overlaying
                  chunk highlights.
              Facet—ContentTypeFilter:
                value:
                  query: indemnification clause
                  content_type:
                  - legal:contract
                  max_results: 5
                summary: Facet — content type filter
                description: Search only documents classified as legal contracts.
              Facet—AttributeFilter:
                value:
                  query: compliance requirements
                  workspace_id:
                  - 42
                  content_type:
                  - legal
                  attribute:
                  - jurisdiction:FR
                  - effective_date:>2024-01-01
                summary: Facet — attribute filter
                description: Search documents with specific attribute values, combined
                  with workspace scoping.
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SearchRequest'
            examples:
              TextSearch—ScopedToWorkspace:
                value:
                  query: authentication system JWT tokens
                  max_results: 5
                  workspace_id:
                  - 42
                summary: Text search — scoped to workspace
                description: Search within a specific workspace using hybrid text
                  search with reranking.
              TextSearch—ScopedToFiles:
                value:
                  query: quarterly revenue forecast
                  max_results: 3
                  file_id:
                  - 101
                  - 102
                summary: Text search — scoped to files
                description: Search specific files only.
              TextSearch—AcrossAllDocuments:
                value:
                  query: onboarding process
                  max_results: 10
                summary: Text search — across all documents
                description: Search across all documents the API key has access to.
              RawRetrieval—SkipScoring:
                value:
                  query: incident response playbook
                  max_results: 10
                  relevance_scoring: none
                summary: Raw retrieval — skip scoring
                description: Bypass relevance scoring for lower latency (relevance_scoring="none").
                  scores.relevance will be null.
              TextSearch—WithBoundingBoxes:
                value:
                  query: authentication system JWT tokens
                  max_results: 5
                  include_bboxes: true
                summary: Text search — with bounding boxes
                description: Append merged PDF bounding boxes to each result for overlaying
                  chunk highlights.
              Facet—ContentTypeFilter:
                value:
                  query: indemnification clause
                  content_type:
                  - legal:contract
                  max_results: 5
                summary: Facet — content type filter
                description: Search only documents classified as legal contracts.
              Facet—AttributeFilter:
                value:
                  query: compliance requirements
                  workspace_id:
                  - 42
                  content_type:
                  - legal
                  attribute:
                  - jurisdiction:FR
                  - effective_date:>2024-01-01
                summary: Facet — attribute filter
                description: Search documents with specific attribute values, combined
                  with workspace scoping.
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
              examples:
                TextSearchResult—WithRerankingAndFacetData:
                  value:
                    results:
                    - chunk_id: 550e8400-e29b-41d4-a716-446655440000
                      content: The indemnifying party shall hold harmless and indemnify
                        the other party...
                      score: 0.95
                      scores:
                        text: 0.91
                        vision: null
                        keyword: 0.43
                        multivector: 0.78
                        relevance: 0.95
                      source:
                        file_id: 512
                        filename: customer-nda.pdf
                        title: Customer NDA — Nimbus Labs
                        mime_type: pdf
                        size_bytes: 482113
                        page_start: 3
                        page_end: 4
                        total_pages: 12
                        tags:
                        - id: 7
                          name: confidential
                        content_types:
                        - path: legal:contract:nda
                          label: Non-Disclosure Agreement
                          attribute_values:
                            jurisdiction:
                              value:
                              - FR
                              - US
                              type: multi-select
                            is_mutual:
                              value: true
                              type: boolean
                            counterparty:
                              value: Nimbus Labs
                              type: text
                        external_metadata: null
                      workspace:
                        id: 42
                        name: Legal Team
                  summary: Text search result — with reranking and facet data
                  description: Search with reranking applied (relevance_scoring="scoring_and_filtering",
                    default). score equals scores.relevance (relevance score). Source
                    includes compact content_types with attribute values.
                TextSearchResult—RawRetrieval:
                  value:
                    results:
                    - chunk_id: 550e8400-e29b-41d4-a716-446655440000
                      content: JWT tokens are signed using RS256 and expire after
                        1 hour.
                      score: 1.65
                      scores:
                        text: 0.91
                        vision: null
                        keyword: 0.43
                        multivector: 0.78
                        relevance: null
                      source:
                        file_id: 512
                        filename: auth-system.pdf
                        title: Authentication System Design
                        mime_type: pdf
                        size_bytes: 482113
                        page_start: 3
                        page_end: 4
                        total_pages: 12
                        tags:
                        - id: 7
                          name: security
                        content_types: []
                        external_metadata: null
                      workspace:
                        id: 42
                        name: Engineering Docs
                  summary: Text search result — raw retrieval
                  description: Raw retrieval without reranking (relevance_scoring="none").
                    score is the combined retrieval score (higher is better, no fixed
                    upper bound). scores.relevance is null.
                TextSearchResult—WithBoundingBoxes:
                  value:
                    results:
                    - chunk_id: 550e8400-e29b-41d4-a716-446655440000
                      content: JWT tokens are signed using RS256 and expire after
                        1 hour.
                      score: 0.95
                      scores:
                        text: 0.91
                        vision: null
                        keyword: 0.43
                        multivector: 0.78
                        relevance: 0.95
                      source:
                        file_id: 512
                        filename: auth-system.pdf
                        title: Authentication System Design
                        mime_type: pdf
                        size_bytes: 482113
                        page_start: 3
                        page_end: 4
                        total_pages: 12
                        tags:
                        - id: 7
                          name: security
                        content_types: []
                        external_metadata: null
                      workspace:
                        id: 42
                        name: Engineering Docs
                      bboxes:
                      - page_number: 3
                        x: 47.37
                        y: 528.28
                        width: 280.13
                        height: 95.42
                        unit: pdf_point
                        origin: top_left
                      - page_number: 4
                        x: 41.86
                        y: 98.0
                        width: 285.99
                        height: 158.67
                        unit: pdf_point
                        origin: top_left
                  summary: Text search result — with bounding boxes
                  description: Response when include_bboxes=true. Each result gains
                    a bboxes array of merged rectangles in PDF points (top-left origin,
                    y extending downward). A chunk spanning pages 3 and 4 yields at
                    least one rectangle per page. Empty list for vision/non-PDF/pre-v2.2.1
                    chunks.
                TextSearchResult—RerankerUnavailable:
                  value:
                    results:
                    - chunk_id: 550e8400-e29b-41d4-a716-446655440000
                      content: JWT tokens are signed using RS256 and expire after
                        1 hour.
                      score: 1.65
                      scores:
                        text: 0.91
                        vision: null
                        keyword: 0.43
                        multivector: 0.78
                        relevance: null
                      source:
                        file_id: 512
                        filename: auth-system.pdf
                        title: Authentication System Design
                        mime_type: pdf
                        size_bytes: 482113
                        page_start: 3
                        page_end: 4
                        total_pages: 12
                        tags: []
                        content_types: []
                        external_metadata: null
                      workspace:
                        id: 42
                        name: Engineering Docs
                    warnings:
                    - code: relevance
                      reason: timeout
                  summary: Text search result — reranker unavailable
                  description: Reranker failed; results returned in retrieval order.
                    score falls back to the combined retrieval score (no fixed upper
                    bound) and scores.relevance is null. The warnings array identifies
                    the degraded signal and failure reason.
                NoMatchingDocuments:
                  value:
                    results: []
                  summary: No matching documents
                  description: Query returned no results — empty array with HTTP 200.
          description: Ranked search results. Empty array if no documents match.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                BadRequest:
                  value:
                    id: null
                    code: 400
                    error: bad_request
                    detail: The request body could not be parsed as valid JSON.
                    doc_url: https://developers.lighton.ai/errors#bad_request
                  summary: Bad Request
          description: Request body is not valid JSON
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InsufficientPermissions:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: None of the provided filters resolve to authorized resources.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
                  summary: Insufficient permissions
          description: API key has no authorized resources matching the provided filters.
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError—ScopingConflict:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      file_id:
                      - error: invalid_combination
                        detail: file_id cannot be combined with workspace_id or tag_id.
                  summary: Validation error — scoping conflict
                ValidationError—MaxResultsOutOfRange:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      max_results:
                      - error: too_large
                        detail: Ensure this value is less than or equal to 100.
                  summary: Validation error — max_results out of range
          description: Field validation failure.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InternalServerError:
                  value:
                    id: null
                    code: 500
                    error: internal_server_error
                    detail: An unexpected error occurred. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#internal_server_error
                  summary: Internal server error
                SearchBackendUnavailable:
                  value:
                    id: null
                    code: 500
                    error: search_backend_unavailable
                    detail: Search backend temporarily unavailable.
                    doc_url: https://developers.lighton.ai/errors#search_backend_unavailable
                  summary: Search backend unavailable
          description: Unexpected server error, or the search backend is unreachable.
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files:
    get:
      operationId: api_v3_files_list
      description: |-
        Retrieve a paginated list of files (documents) accessible to the authenticated user.
        Results are ordered by upload date (newest first) by default.
        When using the `search` parameter, results are ordered by relevance.

        **Public datasets:** instance admins (holding `MANAGE_PUBLIC_DATASET`) always see
        public-dataset files. A company that has opted in (`allow_access_to_public_datasets`)
        with a workspace-scoped API key granting a public workspace also sees its files —
        filter with `workspace_id` to scope the list to it.
      summary: List files accessible to the authenticated user
      parameters:
      - in: query
        name: attribute
        schema:
          type: string
        description: '[Facet] Filter by attribute value. **Repeated `attribute` entries
          are ANDed; values inside one entry are ORed with `|`** (pipe is the recommended
          OR delimiter — comma also works but can be ambiguous with multi-key values).
          Example: `attribute=fiscal_year:2024|2025&attribute=status:active` → (fiscal_year
          2024 OR 2025) AND (status active). Formats: `name` (has any value), `name:value`
          (exact), `name:>value` / `name:>=value` (gt/gte), `name:<value` / `name:<=value`
          (lt/lte), `name:prefix*` (starts with, case-insensitive), `name:*text*`
          (contains, case-insensitive), `name:a|b` (OR). Smart dates: `filing_date:2023`
          (year), `filing_date:2023-06` (month). Type-aware: booleans (true/false),
          multi-select (membership check). Scoped: `content_type(legal:compliance).regulation:AML`.'
        examples:
          EmptySample:
            value: ''
            summary: Empty sample
          HasAttribute:
            value: counterparty
            summary: Has attribute
          TextExactMatch:
            value: counterparty:Nimbus Labs
            summary: Text exact match
          TextPrefix(case-insensitive):
            value: owner_team:Platform*
            summary: Text prefix (case-insensitive)
          TextContains(case-insensitive):
            value: inventors:*MANIA*
            summary: Text contains (case-insensitive)
          SelectExactMatch:
            value: maturity:Approved
            summary: Select exact match
          ORValues(pipe,Recommended):
            value: contract_status:Draft|Executed
            summary: OR values (pipe, recommended)
          ORValues(comma):
            value: contract_status:Draft,Executed
            summary: OR values (comma)
          BooleanValue:
            value: is_mutual:true
            summary: Boolean value
          DateLowerBound:
            value: effective_date:>2024-01-01
            summary: Date lower bound
          DateYearFilter:
            value: filing_date:2023
            summary: Date year filter
          DateYear-monthFilter:
            value: filing_date:2023-06
            summary: Date year-month filter
          NumericLowerBound:
            value: contract_value:>50000
            summary: Numeric lower bound
          Multi-selectMembership:
            value: jurisdiction:FR
            summary: Multi-select membership
          Multi-selectOR:
            value: jurisdiction:FR|US
            summary: Multi-select OR
          ScopedToContentType:
            value: content_type(legal:compliance).regulation:AML
            summary: Scoped to content type
          AND-of-ORs(repeatParam):
            value: fiscal_year:2024|2025
            summary: AND-of-ORs (repeat param)
            description: Repeat attribute for AND logic across different attributes.
              Each param's values are ORed. Use pipe (|) as the OR delimiter to avoid
              ambiguity with comma.
      - in: query
        name: content_type
        schema:
          type: string
        description: '[Facet] Filter by content type path. Multiple values are OR.
          Exact-or-subtree matching by default (e.g. `legal` matches legal, legal:contract).
          Wildcards: `*contract*` (contains), `legal:contract*` (prefix).'
        examples:
          EmptySample:
            value: ''
            summary: Empty sample
          LegalNDASample:
            value: legal:contract:nda
            summary: Legal NDA sample
          TechDesignDocSample:
            value: tech:specification:design-doc
            summary: Tech design doc sample
          BothSampleRecords:
            value: legal:contract:nda,tech:specification:design-doc
            summary: Both sample records
          ContainsContract:
            value: '*contract*'
            summary: Contains contract
          TechSpecificationSubtree:
            value: tech:specification*
            summary: Tech specification subtree
      - in: query
        name: created_at_after
        schema:
          type: string
          format: date-time
        description: Filter by created_at date range (inclusive, date-only strings
          treated as 00:00:00, e.g., ?created_at_after=2024-01-01&created_at_before=2024-01-01T23:59:59)
      - in: query
        name: created_at_before
        schema:
          type: string
          format: date-time
        description: Filter by created_at date range (inclusive, date-only strings
          treated as 00:00:00, e.g., ?created_at_after=2024-01-01&created_at_before=2024-01-01T23:59:59)
      - in: query
        name: extension
        schema:
          type: string
        description: Filter by file extensions (comma-separated, e.g., ?extension=pdf,docx)
      - in: query
        name: external_metadata__doc_type
        schema:
          type: string
        description: 'Filter by external document type (case-insensitive partial match).
          Only returns documents that have external metadata. Example: ?external_metadata__doc_type=gitlab
          matches ''gitlab issue'', ''gitlab ticket'', ''Gitlab MR'', etc.'
      - in: query
        name: external_metadata__external_id
        schema:
          type: string
        description: 'Filter by external document ID (exact match). Matches the doc_id
          stored in the document''s external metadata. Only returns documents that
          have external metadata. Example: ?external_metadata__external_id=SN-12345'
      - in: query
        name: filename
        schema:
          type: string
        description: Filter by filename (case-insensitive partial match)
      - in: query
        name: group_id
        schema:
          type: string
        description: Filter by group IDs (comma-separated, e.g., ?group_id=1,2,3)
      - in: query
        name: include_details
        schema:
          type: boolean
        description: 'Include detail fields (e.g., TLSH signature, parser, summaries,
          and content type attribute values). Default: false.'
      - in: query
        name: max_documents
        schema:
          type: integer
        description: 'Maximum number of documents to return (default: 50, minimum:
          1, maximum: 500)'
      - in: query
        name: ordering
        schema:
          type: string
        description: 'Sort results by field. Prefix with ''-'' for descending order.
          Allowed fields: created_at, filename, title, total_pages, size. Default:
          -created_at (newest first). Ignored when ''search'' is provided (results
          ordered by relevance).'
      - in: query
        name: owner_id
        schema:
          type: string
        description: Filter by owner user IDs (comma-separated, e.g., ?owner_id=1,2,3)
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      - in: query
        name: search
        schema:
          type: string
        description: Semantic search query. When provided, results are ordered by
          combined retrieval score descending. No relevance scoring is applied — scores.relevance
          is always null in search_details chunks.
      - in: query
        name: search_details
        schema:
          type: boolean
        description: When true (and search is provided), include top relevant chunk(s)
          per document.
      - in: query
        name: search_details_chunks_limit
        schema:
          type: integer
        description: 'Max number of relevant chunks to return per document when search_details=true
          (1-10, default: 3).'
      - in: query
        name: status
        schema:
          type: string
          enum:
          - converting
          - embedded
          - embedding
          - embedding_failed
          - fail
          - parsed
          - parsing
          - parsing_failed
          - pending
          - pending_conversion
          - updating
        description: Filter by status values (comma-separated, e.g., ?status=pending,embedded)
      - in: query
        name: status_vision
        schema:
          type: string
          enum:
          - '-'
          - embedded
          - fail
          - pending
          - processing
        description: Filter by vision status values (comma-separated, e.g., ?status_vision=pending,embedded)
      - in: query
        name: tag_id
        schema:
          type: string
        description: Filter by tag IDs (comma-separated, e.g., ?tag_id=1,2,3)
      - in: query
        name: title
        schema:
          type: string
        description: Filter by title (case-insensitive partial match)
      - in: query
        name: total_pages_max
        schema:
          type:
          - integer
          - 'null'
          maximum: 2147483647
          minimum: -2147483648
        description: Filter by total pages range (e.g., ?total_pages_min=10&total_pages_max=50)
      - in: query
        name: total_pages_min
        schema:
          type:
          - integer
          - 'null'
          maximum: 2147483647
          minimum: -2147483648
        description: Filter by total pages range (e.g., ?total_pages_min=10&total_pages_max=50)
      - in: query
        name: updated_at_after
        schema:
          type: string
          format: date-time
        description: Filter by updated_at date range (inclusive, date-only strings
          treated as 00:00:00, e.g., ?updated_at_after=2024-01-01&updated_at_before=2024-01-01T23:59:59)
      - in: query
        name: updated_at_before
        schema:
          type: string
          format: date-time
        description: Filter by updated_at date range (inclusive, date-only strings
          treated as 00:00:00, e.g., ?updated_at_after=2024-01-01&updated_at_before=2024-01-01T23:59:59)
      - in: query
        name: upload_session_uuid
        schema:
          type: string
        description: Filter by upload session UUID (e.g., ?upload_session_uuid=123e4567-e89b-12d3-a456-426614174000)
      - in: query
        name: workspace_id
        schema:
          type: string
        description: Filter by workspace IDs (comma-separated, e.g., ?workspace_id=1,2,3)
      tags:
      - Files
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedFileListResponseSerializerV3List'
              examples:
                DefaultCompactResponse:
                  value:
                    count: 123
                    next: http://api.example.org/accounts/?page=4
                    previous: http://api.example.org/accounts/?page=2
                    results:
                    - - id: 124
                        filename: customer_nda.pdf
                        workspace:
                          id: 3
                          name: Legal Team
                          workspace_type: shared
                        summaries: []
                        title: Customer NDA
                        extension: pdf
                        status: embedded
                        status_vision: embedded
                        created_at: '2024-01-14T14:20:00Z'
                        updated_at: '2024-01-14T14:22:00Z'
                        total_pages: 8
                        tags:
                        - id: 7
                          name: confidential
                          auto_assigned: true
                        - id: 12
                          name: Q1-2026
                          auto_assigned: false
                        created_by:
                          id: 42
                          first_name: Jane
                          last_name: Doe
                          username: jdoe
                        external_metadata:
                          external_id: legal-doc-456789
                          doc_type: nda
                          additional_metadata:
                            external_url: https://contracts.example.com/legal/customer-nda
                        content_types:
                        - path: legal:contract:nda
                          label: Non-Disclosure Agreement
                      - id: 123
                        filename: design_doc.pdf
                        workspace:
                          id: 1
                          name: Engineering Team
                          workspace_type: shared
                        summaries:
                        - language: en
                          summary: This document outlines Q4 initiatives...
                        title: Retrieval Service Design Document
                        extension: pdf
                        status: embedded
                        status_vision: embedded
                        created_at: '2024-01-15T10:30:00Z'
                        updated_at: '2024-01-15T10:35:00Z'
                        total_pages: 25
                        size: 2458624
                        tags:
                        - id: 10
                          name: Project X
                          auto_assigned: false
                        created_by:
                          id: 42
                          first_name: Jane
                          last_name: Doe
                          username: jdoe
                        content_types: []
                  summary: Default compact response
                  description: Compact content types (path and label only — no attribute
                    values). Null fields omitted.
                WithIncludeDetails=true(mid-expanded):
                  value:
                    count: 123
                    next: http://api.example.org/accounts/?page=4
                    previous: http://api.example.org/accounts/?page=2
                    results:
                    - - id: 124
                        filename: customer_nda.pdf
                        workspace:
                          id: 3
                          name: Legal Team
                          workspace_type: custom
                        summaries:
                        - language: en
                          summary: Non-disclosure agreement between LightOn and Nimbus
                            Labs.
                        title: Customer NDA
                        extension: pdf
                        status: embedded
                        status_vision: embedded
                        created_at: '2024-01-14T14:20:00Z'
                        updated_at: '2024-01-14T14:22:00Z'
                        total_pages: 8
                        tags:
                        - id: 7
                          name: confidential
                          auto_assigned: true
                        - id: 12
                          name: Q1-2026
                          auto_assigned: false
                        created_by:
                          id: 42
                          first_name: Jane
                          last_name: Doe
                          username: jdoe
                        signature: T1A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2
                        parser: v2.2.1
                        content_types:
                        - code: nda
                          path: legal:contract:nda
                          label: Non-Disclosure Agreement
                          breadcrumb:
                          - code: legal
                            path: legal
                            label: Legal
                          - code: contract
                            path: legal:contract
                            label: Contract
                          - code: nda
                            path: legal:contract:nda
                            label: Non-Disclosure Agreement
                          attribute_values:
                            jurisdiction:
                              value:
                              - FR
                              - US
                              type: multi-select
                              label: Jurisdiction
                            is_mutual:
                              value: true
                              type: boolean
                              label: Is Mutual
                  summary: With include_details=true (mid-expanded)
                  description: Adds summaries, signature, parser. Content types gain
                    code, structured breadcrumb (ancestor chain with code/path/label
                    per node), and attribute values. Attribute values use compact
                    format (no schema metadata).
                WithSearch+SearchDetails=true:
                  value:
                    count: 123
                    next: http://api.example.org/accounts/?page=4
                    previous: http://api.example.org/accounts/?page=2
                    results:
                    - - id: 123
                        filename: design_doc.pdf
                        workspace:
                          id: 1
                          name: Engineering Team
                          workspace_type: shared
                        summaries:
                        - language: en
                          summary: This document outlines Q4 initiatives...
                        title: Retrieval Service Design Document
                        extension: pdf
                        status: embedded
                        status_vision: embedded
                        created_at: '2024-01-15T10:30:00Z'
                        updated_at: '2024-01-15T10:35:00Z'
                        total_pages: 25
                        size: 2458624
                        tags:
                        - id: 10
                          name: Project X
                          auto_assigned: false
                        created_by:
                          id: 42
                          first_name: Jane
                          last_name: Doe
                          username: jdoe
                        content_types:
                        - path: tech:specification:design-doc
                          label: Design Document
                        search_details:
                          relevant_chunks:
                          - text: This paragraph is a representative excerpt of the
                              highest-ranked chunk.
                            chunk_type: text
                            score: 1.84
                            scores:
                              text: 0.82
                              vision: null
                              keyword: 0.71
                              multivector: 0.6
                              relevance: null
                  summary: With search + search_details=true
                  description: When search is active with search_details=true, each
                    file includes relevant chunks.
                ListOfFiles(withIncludeDetails=true):
                  value:
                    count: 123
                    next: http://api.example.org/accounts/?page=4
                    previous: http://api.example.org/accounts/?page=2
                    results:
                    - - id: 123
                        filename: design_doc.pdf
                        workspace:
                          id: 1
                          name: Engineering Team
                          workspace_type: shared
                        summaries:
                        - language: en
                          summary: This document outlines Q4 initiatives...
                        title: Retrieval Service Design Document
                        extension: pdf
                        status: embedded
                        status_vision: embedded
                        created_at: '2024-01-15T10:30:00Z'
                        updated_at: '2024-01-15T10:35:00Z'
                        total_pages: 25
                        size: 2458624
                        tags: []
                        created_by:
                          id: 42
                          first_name: Jane
                          last_name: Doe
                          username: jdoe
                        signature: T1A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6A7B8C9D0E1F2
                        parser: v2.2.1
                        content_types:
                        - path: tech:specification:design-doc
                          label: Design Document
                        attributes:
                        - name: owner_team
                          label: Owner Team
                          value: Platform Engineering
                          type: text
                        - name: maturity
                          label: Maturity
                          value: Approved
                          type: select
                        - name: component
                          label: Component
                          value: Document Retrieval Service
                          type: text
                      - id: 124
                        filename: customer_nda.pdf
                        workspace:
                          id: 3
                          name: Legal Team
                          workspace_type: shared
                        summaries: []
                        title: Customer NDA
                        extension: pdf
                        status: embedded
                        status_vision: embedded
                        created_at: '2024-01-14T14:20:00Z'
                        updated_at: '2024-01-14T14:22:00Z'
                        total_pages: 8
                        tags: []
                        created_by:
                          id: 43
                          first_name: John
                          last_name: Smith
                          username: jsmith
                        signature: T1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6A7B8C9D0E1F2G3
                        parser: v2.2.1
                        content_types:
                        - path: legal:contract:nda
                          label: Non-Disclosure Agreement
                        attributes:
                        - name: jurisdiction
                          label: Jurisdiction
                          value:
                          - FR
                          - US
                          type: multi_select
                        - name: confidentiality_level
                          label: Confidentiality Level
                          value: Confidential
                          type: select
                        - name: parties
                          label: Parties
                          value: LightOn, Nimbus Labs
                          type: text
                        - name: contract_status
                          label: Contract Status
                          value: Executed
                          type: select
                        - name: counterparty
                          label: Counterparty
                          value: Nimbus Labs
                          type: text
                        - name: is_mutual
                          label: Is Mutual
                          value: true
                          type: boolean
                  summary: List of files (with include_details=true)
          description: List of files accessible to the authenticated user
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    post:
      operationId: api_v3_files_create
      description: |+
        Upload a file to a workspace.

        Files are added to an upload session and queued for asynchronous processing. To track progress, retrieve the file details using the GET endpoints to check the current status.

        **Idempotent upload:** When `external_metadata.external_id` is provided and a manually-uploaded document with the same external ID already exists in the target workspace, the existing document is returned with `200 OK` instead of creating a duplicate. This makes bulk re-runs safe without requiring a pre-check. Datasource-imported documents are not affected.

        **Accepted file formats:** `csv`, `doc`, `docx`, `htm`, `html`, `jpeg`, `jpg`, `md`, `odp`, `odt`, `pdf`, `png`, `ppt`, `pptx`, `txt`, `xhtml`, `xls`, `xlsx`

        **Customization Options:**
        - `title`: Customize the document title (defaults to filename without extension)
        - `filename`: Override the uploaded filename
        - `parser`: Specify a custom ingestion pipeline instead of using the default

      summary: Upload a file
      tags:
      - Files
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/FileCreateRequestSerializerV3'
            examples:
              BasicFileUpload:
                value:
                  file: (binary file data)
                  workspace_id: 42
                summary: Basic file upload
                description: Upload a PDF file with only required fields
              FileUploadWithCustomMetadataAndTags:
                value:
                  file: (binary file data)
                  workspace_id: 42
                  filename: Q4_Report_2025.pdf
                  title: Q4 Financial Report
                  tags:
                  - 1
                  - 2
                summary: File upload with custom metadata and tags
                description: 'Upload a file with custom filename, title, and manual
                  tag assignment. Tags can be sent as a JSON array string (e.g., ''[1,2]'')
                  or as multiple form fields with the same name. '
              IdempotentUploadWithExternalId:
                value:
                  file: (binary file data)
                  workspace_id: 42
                  external_metadata:
                    external_id: hupd:13144833
                summary: Idempotent upload with external_id
                description: Upload with `external_id` for idempotent re-runs. If
                  a manually-uploaded document with the same `external_id` already
                  exists in the workspace, the server returns 200 OK with the existing
                  document instead of creating a duplicate. Datasource-imported documents
                  are not affected — idempotency is scoped to manual uploads only.
              FileUploadWithExternalMetadata:
                value:
                  file: (binary file data)
                  workspace_id: 42
                  external_metadata:
                    external_id: SRV-456789
                    doc_type: incident
                    additional_metadata:
                      external_url: https://servicenow.example.com/incident/SRV-456789
                      external_full_path: ServiceNow > Incidents > SRV-456789
                      created_at: '2024-01-10T08:00:00Z'
                      modified_at: '2024-01-12T16:45:00Z'
                summary: File upload with external metadata
                description: Upload a file that originates from an external system
                  (e.g. ServiceNow, SharePoint). `external_metadata` must be sent
                  as a JSON string when using multipart/form-data. `external_id` is
                  required; `doc_type` and `additional_metadata` are optional.
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/FileCreateRequestSerializerV3'
            examples:
              BasicFileUpload:
                value:
                  file: (binary file data)
                  workspace_id: 42
                summary: Basic file upload
                description: Upload a PDF file with only required fields
              FileUploadWithCustomMetadataAndTags:
                value:
                  file: (binary file data)
                  workspace_id: 42
                  filename: Q4_Report_2025.pdf
                  title: Q4 Financial Report
                  tags:
                  - 1
                  - 2
                summary: File upload with custom metadata and tags
                description: 'Upload a file with custom filename, title, and manual
                  tag assignment. Tags can be sent as a JSON array string (e.g., ''[1,2]'')
                  or as multiple form fields with the same name. '
              IdempotentUploadWithExternalId:
                value:
                  file: (binary file data)
                  workspace_id: 42
                  external_metadata:
                    external_id: hupd:13144833
                summary: Idempotent upload with external_id
                description: Upload with `external_id` for idempotent re-runs. If
                  a manually-uploaded document with the same `external_id` already
                  exists in the workspace, the server returns 200 OK with the existing
                  document instead of creating a duplicate. Datasource-imported documents
                  are not affected — idempotency is scoped to manual uploads only.
              FileUploadWithExternalMetadata:
                value:
                  file: (binary file data)
                  workspace_id: 42
                  external_metadata:
                    external_id: SRV-456789
                    doc_type: incident
                    additional_metadata:
                      external_url: https://servicenow.example.com/incident/SRV-456789
                      external_full_path: ServiceNow > Incidents > SRV-456789
                      created_at: '2024-01-10T08:00:00Z'
                      modified_at: '2024-01-12T16:45:00Z'
                summary: File upload with external metadata
                description: Upload a file that originates from an external system
                  (e.g. ServiceNow, SharePoint). `external_metadata` must be sent
                  as a JSON string when using multipart/form-data. `external_id` is
                  required; `doc_type` and `additional_metadata` are optional.
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileCreateResponseSerializerV3'
              examples:
                Idempotent—DocumentAlreadyExists:
                  value:
                    id: 12345
                    filename: 13144833.md
                    workspace:
                      id: 42
                      name: My Workspace
                      workspace_type: shared
                    title: Patent 13144833
                    extension: md
                    status: embedded
                    status_vision: null
                    created_at: '2025-03-01T10:30:00Z'
                    updated_at: '2025-03-01T10:30:00Z'
                    total_pages: 3
                    tags: []
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    upload_session_uuid: null
                    external_metadata:
                      external_id: hupd:13144833
                      doc_type: ''
                      additional_metadata: {}
                    message: Document already exists (idempotent)
                  summary: Idempotent — document already exists
                  description: The document with this external_id was already uploaded
                    to this workspace. No new document is created. The response body
                    is identical to a normal upload response.
          description: Document already exists (idempotent). Returned when `external_metadata.external_id`
            matches a manually-uploaded document in the same workspace. The existing
            document is returned without creating a duplicate.
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileCreateResponseSerializerV3'
              examples:
                FileUploadedSuccessfully:
                  value:
                    id: 12345
                    filename: document.pdf
                    workspace:
                      id: 42
                      name: My Workspace
                      workspace_type: shared
                    summaries: []
                    title: document
                    extension: pdf
                    status: pending
                    status_vision: null
                    created_at: '2025-03-01T10:30:00Z'
                    updated_at: '2025-03-01T10:30:00Z'
                    total_pages: 0
                    tags: []
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    upload_session_uuid: 550e8400-e29b-41d4-a716-446655440000
                    external_metadata: null
                    message: File queued for processing
                  summary: File uploaded successfully
                FileUploadedWithTags:
                  value:
                    id: 12346
                    filename: compliance_doc.pdf
                    workspace:
                      id: 42
                      name: My Workspace
                      workspace_type: shared
                    summaries: []
                    title: Compliance Document
                    extension: pdf
                    status: pending
                    status_vision: null
                    created_at: '2025-03-01T10:35:00Z'
                    updated_at: '2025-03-01T10:35:00Z'
                    total_pages: 0
                    tags:
                    - id: 1
                      name: Compliance
                      auto_assigned: false
                    - id: 2
                      name: Legal
                      auto_assigned: false
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    upload_session_uuid: 550e8400-e29b-41d4-a716-446655440000
                    external_metadata: null
                    message: File queued for processing
                  summary: File uploaded with tags
                FileUploadedWithExternalMetadata:
                  value:
                    id: 12348
                    filename: SRV-456789.pdf
                    workspace:
                      id: 42
                      name: My Workspace
                      workspace_type: shared
                    summaries: []
                    title: SRV-456789
                    extension: pdf
                    status: pending
                    status_vision: null
                    created_at: '2025-03-01T10:40:00Z'
                    updated_at: '2025-03-01T10:40:00Z'
                    total_pages: 0
                    tags: []
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    upload_session_uuid: 550e8400-e29b-41d4-a716-446655440000
                    external_metadata:
                      external_id: SRV-456789
                      doc_type: incident
                      additional_metadata:
                        external_url: https://servicenow.example.com/incident/SRV-456789
                        external_full_path: ServiceNow > Incidents > SRV-456789
                    message: File queued for processing
                  summary: File uploaded with external metadata
                  description: Upload response when external_metadata was provided.
                    The record is created synchronously and returned immediately.
          description: File queued for processing successfully
        '207':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileCreateResponseSerializerV3'
              examples:
                FileUploadedWithTagError:
                  value:
                    id: 12347
                    filename: document.pdf
                    workspace:
                      id: 42
                      name: My Workspace
                      workspace_type: shared
                    summaries: []
                    title: document
                    extension: pdf
                    status: pending
                    status_vision: null
                    created_at: '2025-03-01T10:40:00Z'
                    updated_at: '2025-03-01T10:40:00Z'
                    total_pages: 0
                    tags: []
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    upload_session_uuid: 550e8400-e29b-41d4-a716-446655440000
                    external_metadata: null
                    message: 'Document uploaded successfully, but tag assignment failed:
                      Invalid or unauthorized tag IDs: 999'
                  summary: File uploaded with tag error
                  description: Document uploaded successfully but tags failed to assign
          description: Document uploaded but tag assignment failed (partial success)
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                StorageLimitReached:
                  value:
                    id: null
                    code: 400
                    error: STORAGE_LIMIT_REACHED
                    detail: The custom workspace storage limit for your company is
                      500 MB and you are currently using 487.3 MB. Delete stale documents
                      or ask your company admin to request an increase of your storage
                      quota.
                    doc_url: https://developers.lighton.ai/errors#STORAGE_LIMIT_REACHED
                  summary: Storage limit reached
                UploadsDisabled:
                  value:
                    id: null
                    code: 400
                    error: UPLOADS_DISABLED
                    detail: Uploads are disabled for the custom workspace. The storage
                      limit is set to 0 MB. Ask your company admin to request an increase
                      of your storage quota.
                    doc_url: https://developers.lighton.ai/errors#UPLOADS_DISABLED
                  summary: Uploads disabled
          description: Domain error — the upload exceeds the workspace storage limit
            or uploads are disabled. The domain code is carried in `error` and the
            limit/usage in `detail`.
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                MissingRequiredField:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      workspace_id:
                      - error: required
                        detail: This field is required.
                  summary: Missing required field
                InvalidFileType:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      file:
                      - error: invalid
                        detail: File extension not supported.
                  summary: Invalid file type
                SyncedWorkspace:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      non_field_errors:
                      - error: invalid
                        detail: Cannot manually upload documents to a workspace configured
                          for synced documents.
                  summary: Synced workspace
          description: Validation error — missing/invalid fields or a synced workspace.
            Per-field errors in `fields`.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                TooManyRequests:
                  value:
                    id: null
                    code: 429
                    error: too_many_requests
                    detail: Too many requests. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#too_many_requests
                  summary: Too Many Requests
          description: Too many requests
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files/bulk-delete:
    post:
      operationId: api_v3_files_bulk_delete_create
      description: |-
        Permanently delete multiple files in a single request.

        **Authorization (applied to every file in the request):**
        - Visibility: file must be accessible to the user → 404 if any are not found
        - Delete permission: user must have the right to delete each file → 403 if any are denied
        - Workspace type: workspace must not be sync-managed → 400 if any are synced

        **Public datasets:** instance admins (`MANAGE_PUBLIC_DATASET`) can bulk-delete public-dataset files. A workspace-scoped API key with read-only access to a public dataset can see the file (so it counts toward visibility) but gets 403 on the delete-permission check — public datasets are read-only for opted-in companies.

        Returns 204 (No Content) on success.
      summary: Delete multiple files in a single request
      tags:
      - Files
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileBulkDeleteRequestSerializerV3'
            examples:
              BulkDeleteRequest:
                value:
                  ids:
                  - 123
                  - 124
                  - 125
                summary: Bulk delete request
        required: true
      security:
      - bearerAuth: []
      responses:
        '204':
          description: Files deleted successfully (no content returned)
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                SyncedWorkspace:
                  value:
                    id: null
                    code: 400
                    error: bad_request
                    detail: Cannot manually delete documents from a workspace configured
                      for synced documents. Documents in this workspace can only be
                      managed through external datasources.
                    doc_url: https://developers.lighton.ai/errors#bad_request
                  summary: Synced workspace
          description: Synced workspace constraint — documents can only be managed
            through external datasources.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files/{id}:
    get:
      operationId: api_v3_files_retrieve
      description: |-
        Retrieve detailed information for a single file by its ID.
        Only files that the authenticated user is authorized to access will be returned.
        Returns 404 if the file does not exist or the user does not have access.

        Query Parameters:
        - include_content: Set to 'true' to include the full text content of the document (default: false)

        The response includes comprehensive document details including:
        - Basic metadata (id, filename, title, extension, dates, page count)
        - Full text content of the document (only when include_content=true)
        - Processing status (status, status_vision, status_detail if failed)
        - Associated tags and workspace information
        - File size (if available)
        - Parser/ingestion pipeline (if available, after parsing starts)
        - Signature (TLSH hash for duplicate detection)
        - Facet content types and nested attribute values (full expanded with attribute definitions)

        **Public datasets:** reachable by instance admins (`MANAGE_PUBLIC_DATASET`) unconditionally,
        and by a company that has opted in (`allow_access_to_public_datasets`) with a
        workspace-scoped API key granting the file's public workspace.
      summary: Retrieve a single file by ID
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this Document.
        required: true
      - in: query
        name: include_content
        schema:
          type: boolean
        description: 'When true, include the full text content of the document in
          the response (default: false). Recommended to only enable when needed as
          content can be large.'
      tags:
      - Files
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileRetrieveResponseSerializerV3'
              examples:
                FileDetail(fullExpanded):
                  value:
                    id: 124
                    filename: customer_nda.pdf
                    workspace:
                      id: 3
                      name: Legal Team
                      workspace_type: custom
                    summaries:
                    - language: en
                      summary: Non-disclosure agreement between LightOn and Nimbus
                        Labs.
                    title: Customer NDA
                    extension: pdf
                    status: embedded
                    status_vision: embedded
                    created_at: '2024-01-14T14:20:00Z'
                    updated_at: '2024-01-14T14:22:00Z'
                    total_pages: 8
                    tags:
                    - id: 7
                      name: confidential
                      auto_assigned: true
                    - id: 12
                      name: Q1-2026
                      auto_assigned: false
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    signature: T1A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2
                    external_metadata:
                      external_id: legal-doc-456789
                      doc_type: nda
                      additional_metadata:
                        external_url: https://contracts.example.com/legal/customer-nda
                    content_types:
                    - code: nda
                      path: legal:contract:nda
                      label: Non-Disclosure Agreement
                      breadcrumb:
                      - code: legal
                        path: legal
                        label: Legal
                      - code: contract
                        path: legal:contract
                        label: Contract
                      - code: nda
                        path: legal:contract:nda
                        label: Non-Disclosure Agreement
                      attribute_values:
                        jurisdiction:
                          value:
                          - FR
                          - US
                          type: multi-select
                          attribute:
                            name: jurisdiction
                            label: Jurisdiction
                            type: multi-select
                            required: true
                            choices:
                            - FR
                            - US
                            - UK
                            - DE
                        is_mutual:
                          value: true
                          type: boolean
                          attribute:
                            name: is_mutual
                            label: Is Mutual
                            type: boolean
                            required: false
                        counterparty:
                          value: Nimbus Labs
                          type: text
                          attribute:
                            name: counterparty
                            label: Counterparty
                            type: text
                            required: false
                  summary: File detail (full expanded)
                  description: Detail always includes summaries, signature, and full
                    expanded content types with code, breadcrumb, and attribute definitions
                    (type, required, choices).
                FileDetailWithContent:
                  value:
                    id: 123
                    filename: design_doc.pdf
                    workspace:
                      id: 1
                      name: Engineering Team
                      workspace_type: custom
                    summaries:
                    - language: en
                      summary: This document outlines Q4 initiatives...
                    title: Retrieval Service Design Document
                    extension: pdf
                    status: embedded
                    status_vision: embedded
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T10:35:00Z'
                    total_pages: 25
                    size: 2458624
                    tags:
                    - id: 10
                      name: Project X
                      auto_assigned: false
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    signature: T1A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2
                    content: |-
                      Retrieval Service Design Document

                      Overview

                      This document outlines the service architecture, retrieval flow, and implementation decisions...
                    pages:
                    - index: 1
                      markdown: |-
                        # Retrieval Service Design Document

                        ## Overview

                        ...
                    - index: 2
                      markdown: |-
                        ## Retrieval flow

                        ...
                    content_types:
                    - code: design-doc
                      path: tech:specification:design-doc
                      label: Design Document
                      breadcrumb:
                      - code: tech
                        path: tech
                        label: Tech
                      - code: specification
                        path: tech:specification
                        label: Specification
                      - code: design-doc
                        path: tech:specification:design-doc
                        label: Design Document
                      attribute_values:
                        maturity:
                          value: Approved
                          type: select
                          label: Maturity
                          attribute:
                            name: maturity
                            label: Maturity
                            type: select
                            required: true
                            choices:
                            - Draft
                            - In Review
                            - Approved
                            - Deprecated
                        owner_team:
                          value: Platform Engineering
                          type: text
                          label: Owner Team
                          attribute:
                            name: owner_team
                            label: Owner Team
                            type: text
                            required: false
                  summary: File detail with content
                  description: With include_content=true, the full document text is
                    included as the flat `content` string and as canonical per-page
                    objects under `pages` (`{ index, markdown }`, the same shape returned
                    by /parse and /ocr). `content` is retained for now; prefer `pages`.
          description: Detailed file information. Always uses full expanded content
            types (Tier 3) with breadcrumb, code, and attribute definitions including
            type, required, and choices.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    patch:
      operationId: api_v3_files_partial_update
      description: |
        Update mutable fields of a file (document).

        **Updatable fields:**
        - `title`: Update the document title
        - `tags`: Replace ALL tags for the document (both manual and auto-assigned)
        - `external_metadata`: Create or update external source metadata

        **Tag replacement behavior:**
        - Providing a tags array replaces ALL existing tags (manual and auto-assigned)
        - To remove all tags, send `[0]` (sentinel value for multipart format)
        - Omitting `tags` field leaves tags unchanged
        - New tags are marked as manually assigned (`auto_assigned=False`)

        **External metadata behavior:**
        - When creating for the first time, `external_id` is required
        - When updating existing metadata, `external_id` is optional (existing value is preserved)
        - Fields in `additional_metadata` are merged (not replaced) with existing values

        **Validation:**
        - Returns 400 if only immutable fields are provided (mutable fields: 'external_metadata', 'tags', 'title')
        - Returns 400 if tag IDs are invalid or don't belong to user's company
        - Returns 404 if document doesn't exist or user doesn't have access

        **Public datasets:** editing a public-dataset file requires the instance-admin `MANAGE_PUBLIC_DATASET` permission. A workspace-scoped API key with read access (company opted in via `allow_access_to_public_datasets`) can see the file but gets 403, not 404, when attempting to edit it — public datasets are read-only.
      summary: Update file metadata
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this Document.
        required: true
      tags:
      - Files
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedFileUpdateRequestSerializerV3'
            examples:
              UpdateTitleOnly:
                value:
                  title: Updated Document Title
                summary: Update title only
                description: Update only the document title
              ReplaceAllTags:
                value:
                  tags:
                  - 1
                  - 2
                summary: Replace all tags
                description: Replace all existing tags (both manual and auto-assigned)
                  with new ones. Tags can be sent as a JSON array string (e.g., '[1,2]')
                  or as multiple form fields with the same name.
              RemoveAllTags:
                value:
                  tags:
                  - 0
                summary: Remove all tags
                description: Remove all tags using sentinel value [0]
              CreateExternalMetadata:
                value:
                  external_metadata:
                    external_id: gitlab-issue-456
                    doc_type: gitlab_issue
                    additional_metadata:
                      external_url: https://gitlab.example.com/project/-/issues/456
                      name: Fix authentication bug
                summary: Create external metadata
                description: Attach external source metadata to a document that has
                  none yet. `external_id` is required for creation. `external_metadata`
                  must be sent as a JSON string when using multipart/form-data.
              UpdateExistingExternalMetadata:
                value:
                  external_metadata:
                    additional_metadata:
                      last_synced_at: '2024-01-15T10:00:00Z'
                      name: Updated Name
                summary: Update existing external metadata
                description: Update fields on an existing external metadata record.
                  `external_id` is optional when a record already exists — it will
                  be preserved if omitted. Fields inside `additional_metadata` are
                  merged with existing values, not replaced.
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedFileUpdateRequestSerializerV3'
            examples:
              UpdateTitleOnly:
                value:
                  title: Updated Document Title
                summary: Update title only
                description: Update only the document title
              ReplaceAllTags:
                value:
                  tags:
                  - 1
                  - 2
                summary: Replace all tags
                description: Replace all existing tags (both manual and auto-assigned)
                  with new ones. Tags can be sent as a JSON array string (e.g., '[1,2]')
                  or as multiple form fields with the same name.
              RemoveAllTags:
                value:
                  tags:
                  - 0
                summary: Remove all tags
                description: Remove all tags using sentinel value [0]
              CreateExternalMetadata:
                value:
                  external_metadata:
                    external_id: gitlab-issue-456
                    doc_type: gitlab_issue
                    additional_metadata:
                      external_url: https://gitlab.example.com/project/-/issues/456
                      name: Fix authentication bug
                summary: Create external metadata
                description: Attach external source metadata to a document that has
                  none yet. `external_id` is required for creation. `external_metadata`
                  must be sent as a JSON string when using multipart/form-data.
              UpdateExistingExternalMetadata:
                value:
                  external_metadata:
                    additional_metadata:
                      last_synced_at: '2024-01-15T10:00:00Z'
                      name: Updated Name
                summary: Update existing external metadata
                description: Update fields on an existing external metadata record.
                  `external_id` is optional when a record already exists — it will
                  be preserved if omitted. Fields inside `additional_metadata` are
                  merged with existing values, not replaced.
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileRetrieveResponseSerializerV3'
              examples:
                FileUpdatedSuccessfully:
                  value:
                    id: 123
                    filename: project_proposal.pdf
                    workspace:
                      id: 1
                      name: Engineering Team
                    summaries:
                    - language: en
                      summary: This document outlines Q4 initiatives...
                    title: Updated Document Title
                    extension: pdf
                    status: embedded
                    status_vision: embedded
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T11:45:00Z'
                    total_pages: 25
                    size: 2458624
                    tags:
                    - id: 1
                      name: Compliance
                      auto_assigned: false
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    signature: T1A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6A7B8C9D0E1F2
                    parser: v2.2.1
                    external_metadata: null
                    content_types:
                    - path: tech:specification:design-doc
                      label: Design Document
                      labels:
                      - Tech
                      - Specification
                      - Design Document
                      attributes:
                      - name: owner_team
                        label: Owner Team
                        value: Platform Engineering
                        type: text
                      - name: maturity
                        label: Maturity
                        value: Approved
                        type: select
                      - name: component
                        label: Component
                        value: Document Retrieval Service
                        type: text
                  summary: File updated successfully
                FileUpdatedWithExternalMetadata:
                  value:
                    id: 124
                    filename: customer_nda.pdf
                    workspace:
                      id: 3
                      name: Legal Team
                    summaries: []
                    title: Customer NDA
                    extension: pdf
                    status: embedded
                    status_vision: embedded
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T11:45:00Z'
                    total_pages: 3
                    size: 102400
                    tags: []
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    signature: T1A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6A7B8C9D0E1F2
                    external_metadata:
                      external_id: legal-doc-456789
                      doc_type: nda
                      additional_metadata:
                        external_url: https://contracts.example.com/legal/customer-nda
                        last_synced_at: '2024-01-15T10:00:00Z'
                    content_types:
                    - path: legal:contract:nda
                      label: Non-Disclosure Agreement
                      labels:
                      - Legal
                      - Contract
                      - Non-Disclosure Agreement
                      attributes:
                      - name: jurisdiction
                        label: Jurisdiction
                        value:
                        - FR
                        - US
                        type: multi-select
                      - name: confidentiality_level
                        label: Confidentiality Level
                        value: Confidential
                        type: select
                      - name: parties
                        label: Parties
                        value: LightOn, Nimbus Labs
                        type: text
                      - name: contract_status
                        label: Contract Status
                        value: Executed
                        type: select
                      - name: counterparty
                        label: Counterparty
                        value: Nimbus Labs
                        type: text
                      - name: is_mutual
                        label: Is Mutual
                        value: true
                        type: boolean
                  summary: File updated with external metadata
          description: File updated successfully
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    delete:
      operationId: api_v3_files_destroy
      description: |-
        Permanently delete a file and all associated data.

        **Requirements:**
        - Delete permission on the document
        - Workspace must allow manual document management (not sync-only)

        **Public datasets:** deleting a public-dataset file requires the instance-admin `MANAGE_PUBLIC_DATASET` permission. A workspace-scoped API key with read access (company opted in via `allow_access_to_public_datasets`) can see the file but gets 403, not 404, when attempting to delete it — public datasets are read-only.

        Returns 204 (No Content) on success.
      summary: Delete a file
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this Document.
        required: true
      tags:
      - Files
      security:
      - bearerAuth: []
      responses:
        '204':
          description: File deleted successfully (no content returned)
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                SyncedWorkspace:
                  value:
                    id: null
                    code: 400
                    error: bad_request
                    detail: Cannot manually delete documents from a workspace configured
                      for synced documents. Documents in this workspace can only be
                      managed through external datasources.
                    doc_url: https://developers.lighton.ai/errors#bad_request
                  summary: Synced workspace
          description: Cannot delete from a synced workspace.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InternalServerError:
                  value:
                    id: null
                    code: 500
                    error: internal_server_error
                    detail: An unexpected error occurred. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#internal_server_error
                  summary: Internal Server Error
          description: An unexpected error occurred
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files/{id}/download:
    get:
      operationId: api_v3_files_download_retrieve
      description: Download a document file. Returns the original file by default.
        Use the purpose parameter to request a specific version (e.g. rendered_pdf
        for frontend viewers).
      summary: Download a document file
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this Document.
        required: true
      - in: query
        name: purpose
        schema:
          type: string
          enum:
          - original
          - rendered_pdf
          - transcript
        description: Which file version to serve. Defaults to 'original'. Falls back
          to 'original' if the requested purpose has no associated file.
      tags:
      - Files
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Binary file content or sanitized markdown text
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files/{id}/tags:
    post:
      operationId: api_v3_files_tags_create
      description: |
        Add one or more tags to a file without affecting existing tags.

        **Behavior:**
        - Adds new tags to the document while preserving existing ones
        - New tags are marked as manually assigned (`auto_assigned=False`)
        - Duplicate tags are ignored (no error if tag already exists on document)

        **Validation:**
        - Returns 400 if tag IDs are invalid or don't belong to user's company
        - Returns 403 if user doesn't have permission to edit the document
        - Returns 404 if document doesn't exist
      summary: Add tags to a file
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        required: true
      tags:
      - Files
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileTaggingAddRequest'
            examples:
              AddSingleTag:
                value:
                  tags:
                  - 1
                summary: Add single tag
                description: Add one tag to a file
              AddMultipleTags:
                value:
                  tags:
                  - 1
                  - 2
                summary: Add multiple tags
                description: Add multiple tags to a file at once
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/FileTaggingAddRequest'
            examples:
              AddSingleTag:
                value:
                  tags:
                  - 1
                summary: Add single tag
                description: Add one tag to a file
              AddMultipleTags:
                value:
                  tags:
                  - 1
                  - 2
                summary: Add multiple tags
                description: Add multiple tags to a file at once
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/FileTaggingAddRequest'
            examples:
              AddSingleTag:
                value:
                  tags:
                  - 1
                summary: Add single tag
                description: Add one tag to a file
              AddMultipleTags:
                value:
                  tags:
                  - 1
                  - 2
                summary: Add multiple tags
                description: Add multiple tags to a file at once
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileRetrieveResponseSerializerV3'
              examples:
                TagsAddedSuccessfully:
                  value:
                    id: 123
                    filename: project_proposal.pdf
                    workspace:
                      id: 1
                      name: Engineering Team
                    summaries:
                    - language: en
                      summary: This document outlines Q4 initiatives...
                    title: Q4 Project Proposal
                    extension: pdf
                    status: embedded
                    status_vision: embedded
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T11:45:00Z'
                    total_pages: 25
                    size: 2458624
                    tags:
                    - id: 1
                      name: Compliance
                      auto_assigned: false
                    - id: 2
                      name: Legal
                      auto_assigned: false
                    created_by:
                      id: 42
                      first_name: Jane
                      last_name: Doe
                      username: jdoe
                    signature: T1A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6A7B8C9D0E1F2
                    parser: v2.2.1
                    message: Added 2 tag(s) to file (duplicates ignored)
                  summary: Tags added successfully
          description: Tags added successfully
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files/{id}/tags/{tag_id}:
    delete:
      operationId: api_v3_files_tags_destroy
      description: |
        Remove a specific tag from a file.

        **Behavior:**
        - Removes the specified tag from the document
        - Works for both manually assigned and auto-assigned tags
        - Idempotent: returns 204 even if tag was not on the document

        **Validation:**
        - Returns 403 if user doesn't have permission to edit the document
        - Returns 404 if document doesn't exist
        - Returns 404 if tag doesn't exist or doesn't belong to user's company
      summary: Remove a tag from a file
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        required: true
      - in: path
        name: tag_id
        schema:
          type: integer
        required: true
      tags:
      - Files
      security:
      - bearerAuth: []
      responses:
        '204':
          description: Tag removed successfully (or was already not on the file)
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/content-types:
    get:
      operationId: api_v3_content_types_retrieve
      description: |-
        List your classification trees: the content types you've adopted
        from the starter templates or created from scratch. This is where you see
        what's available to classify your documents with.

        **Content types are tree-based.** Each tree is an independent classification
        hierarchy (e.g., `legal` → `contract` → `nda`). You can have multiple trees
        side by side (`legal`, `finance`, `compliance`), and a single document can be
        classified under **multiple trees** simultaneously. For instance, a contract
        can be both `legal:contract:nda` and `finance:investment:term-sheet`.

        Each node in the tree can carry **custom attributes** (metadata fields like
        `jurisdiction`, `effective_date`, `contract_value`). Attributes are inherited
        down the tree: a document at `legal:contract:nda` gets attributes from all
        three levels.

        **New here?** Start by browsing available templates at
        `GET /api/v3/content-types/templates`, then adopt the ones you need
        via `POST /api/v3/content-types {"action": "adopt"}`.

        **Query params:**
        - `?query=5G antennas`: filter to content types relevant to a search query
          (uses a first-pass retrieval). Without this param, the full catalog is returned.
        - `?path=legal`: filter to a specific subtree
        - `?path=legal,finance`: multiple subtrees (comma-separated)
        - `?depth=0`: roots only. `?depth=N`: N levels of children.
        - `?include_attributes=true` (default): include attribute definitions per node
        - `?include_attributes=false`: omit attribute definitions for a lighter response

        `query` and `path` can be combined: returns the intersection (only matched
        content types under the requested paths).

        Returns an empty list if no content types have been set up yet.
      summary: List content types
      parameters:
      - in: query
        name: depth
        schema:
          type: integer
        description: Tree depth limit. Omitted = full tree. 0 = roots only.
      - in: query
        name: include_attributes
        schema:
          type: boolean
        description: 'Include attribute definitions per content type node. Default:
          true.'
      - in: query
        name: path
        schema:
          type: string
        description: Content type path(s) to filter (comma-separated).
      - in: query
        name: query
        schema:
          type: string
        description: When provided, filter the catalog to content types found in a
          first-pass retrieval for this query. Without this parameter, the full company
          catalog is returned (existing behavior).
      tags:
      - Facets
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentTypesListResponse'
              examples:
                CompanyContentTypes(default,WithAttributes):
                  value:
                    content_types:
                    - path: legal
                      code: legal
                      label: Legal
                      description: 'Legal documents: contracts, litigation, compliance.'
                      inherit_attributes: true
                      attributes:
                      - name: jurisdiction
                        label: Jurisdiction
                        type: multi-select
                        required: false
                        description: Legal jurisdiction(s) governing the document
                        choices:
                        - FR
                        - US
                        - UK
                        - DE
                      - name: confidentiality_level
                        label: Confidentiality Level
                        type: select
                        required: false
                        description: ''
                        choices:
                        - Public
                        - Internal
                        - Confidential
                        - Strictly Confidential
                      children:
                      - path: legal:contract
                        code: contract
                        label: Contract
                        description: Binding agreements between parties.
                        inherit_attributes: true
                        attributes:
                        - name: jurisdiction
                          label: Jurisdiction
                          type: multi-select
                          required: false
                          description: Legal jurisdiction(s) governing the document
                          choices:
                          - FR
                          - US
                          - UK
                          - DE
                          inherited: true
                        - name: effective_date
                          label: Effective Date
                          type: date
                          required: false
                          description: ''
                          choices: []
                        children:
                        - path: legal:contract:nda
                          code: nda
                          label: Non-Disclosure Agreement
                          description: ''
                          inherit_attributes: true
                          attributes:
                          - name: jurisdiction
                            label: Jurisdiction
                            type: multi-select
                            required: false
                            description: Legal jurisdiction(s) governing the document
                            choices:
                            - FR
                            - US
                            - UK
                            - DE
                            inherited: true
                          - name: effective_date
                            label: Effective Date
                            type: date
                            required: false
                            description: ''
                            choices: []
                            inherited: true
                          - name: counterparty
                            label: Counterparty
                            type: text
                            required: true
                            description: Name of the other party
                            choices: []
                          - name: is_mutual
                            label: Is Mutual
                            type: boolean
                            required: false
                            description: ''
                            choices: []
                    can_edit: true
                  summary: Company content types (default, with attributes)
                  description: Full tree with attribute definitions per node. Children
                    nested recursively.
                WithoutAttributes(?includeAttributes=false):
                  value:
                    content_types:
                    - path: legal
                      code: legal
                      label: Legal
                      description: 'Legal documents: contracts, litigation, compliance.'
                      inherit_attributes: true
                      children:
                      - path: legal:contract
                        code: contract
                        label: Contract
                        description: Binding agreements between parties.
                        inherit_attributes: true
                    can_edit: true
                  summary: Without attributes (?include_attributes=false)
                  description: Lighter response, tree structure only, no attribute
                    definitions.
          description: Company content type tree with optional attribute definitions.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    post:
      operationId: api_v3_content_types_create
      description: |-
        Create, modify, and organise your company's content-type trees and their
        attributes. Every action is idempotent, safe to re-run.

        **Two ways to build your schema:**

        1. **Adopt from starter templates**: import ready-made trees from the seed
           catalog (`GET /api/v3/content-types/templates`). Once adopted, they're
           yours to customize.
        2. **Build from scratch**: create your own trees, nodes, and attributes
           entirely with `define_content_type` and `define_attribute`.

        You can mix both: adopt `legal` from the seeds, then add a custom
        `compliance` tree alongside it. Each tree is independent.

        **Actions:**
        - `adopt`: import trees from the seed catalog (starter templates)
        - `define_content_type`: create or update a tree node (root or child)
        - `undefine_content_type`: delete a node and its entire subtree
        - `define_attribute`: add or update a metadata field on a node
        - `undefine_attribute`: remove a metadata field

        **Building a tree from scratch, example flow:**

        1. Create a root:
           ```json
           {"action": "define_content_type", "code": "compliance", "label": "Compliance"}
           ```
        2. Add children:
           ```json
           {"action": "define_content_type", "parent_path": "compliance", "code": "audit-report", "label": "Audit Report"}
           ```
        3. Add attributes:
           ```json
           {"action": "define_attribute", "content_type_path": "compliance", "name": "owner", "attribute_type": "text"}
           ```
        4. Classify files via `POST /api/v3/files/{id}/facets`:
           ```json
           {"action": "classify", "content_type_path": "compliance:audit-report"}
           ```

        **Attributes** are metadata fields you define on each node. Types:
        `text`, `number`, `date`, `boolean`, `select`, `multi-select`, `rich-text`.
        `select` and `multi-select` require `choices`. Attributes inherit down the
        tree: define `jurisdiction` on `legal` and it's available on all children.

        **Description best practices:** The `description` field on attributes feeds
        into the scope inference endpoint (`POST /api/v3/content-types/scope`),
        where it helps the LLM generate accurate search filters. Use keywords that
        signal the attribute's nature:
        - **Person names**: include "name", "examiner", "inventor", or "author" →
          enables `*value*` wildcard syntax hints
        - **Codes/identifiers**: include "code", "classification", or "identifier" →
          enables exact-match hints (don't guess from topic keywords)

        **Multi-classification:** A single document can be classified under multiple
        content types from different trees (e.g., both `legal:contract:nda` and
        `compliance:audit-report`).

        Available seed roots for `adopt`: finance, healthcare, legal, manufacturing, tech

        Requires admin-level access to modify the company's schema.
      summary: Define content types and attributes
      tags:
      - Facets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentTypeActionRequest'
            examples:
              AdoptSeedRoots:
                value:
                  action: adopt
                  content_types:
                  - legal
                  - finance
                summary: Adopt seed roots
              DefineACompany-originalRootNode:
                value:
                  action: define_content_type
                  code: compliance
                  label: Compliance
                  description: Internal compliance artefacts
                summary: Define a company-original root node
              DefineAChildNodeUnderAnExistingParent:
                value:
                  action: define_content_type
                  parent_path: compliance
                  code: audit-report
                  label: Audit Report
                summary: Define a child node under an existing parent
              UpdateAnExistingNode'sLabel:
                value:
                  action: define_content_type
                  parent_path: compliance
                  code: audit-report
                  label: Internal Audit Report
                summary: Update an existing node's label
                description: Same (parent_path, code) as an earlier call, updates
                  in place.
              DeleteANodeAndCascadeItsSubtree:
                value:
                  action: undefine_content_type
                  content_type_path: compliance:audit-report
                summary: Delete a node and cascade its subtree
              DefineAnAttributeColumnOnANode:
                value:
                  action: define_attribute
                  content_type_path: legal:contract:nda
                  name: jurisdiction
                  attribute_type: multi-select
                  choices:
                  - FR
                  - US
                  - UK
                  - DE
                  - CH
                summary: Define an attribute column on a node
              DefineATextAttribute(personName):
                value:
                  action: define_attribute
                  content_type_path: legal:contract:nda
                  name: counterparty
                  attribute_type: text
                  description: Name of the counterparty or signing entity
                  required: true
                summary: Define a text attribute (person name)
              DefineATextAttribute(code/identifier):
                value:
                  action: define_attribute
                  content_type_path: patent
                  name: uspc_class
                  attribute_type: text
                  description: USPC classification code for the patent
                summary: Define a text attribute (code/identifier)
              DefineANumberAttribute:
                value:
                  action: define_attribute
                  content_type_path: finance:report
                  name: amount
                  attribute_type: number
                summary: Define a number attribute
              DefineADateAttribute:
                value:
                  action: define_attribute
                  content_type_path: legal:contract
                  name: effective_date
                  attribute_type: date
                summary: Define a date attribute
              DefineABooleanAttribute:
                value:
                  action: define_attribute
                  content_type_path: legal:contract:nda
                  name: is_mutual
                  attribute_type: boolean
                summary: Define a boolean attribute
              DefineASelectAttribute:
                value:
                  action: define_attribute
                  content_type_path: tech:specification
                  name: maturity
                  attribute_type: select
                  choices:
                  - Draft
                  - Approved
                  - Deprecated
                summary: Define a select attribute
              DefineARichTextAttribute:
                value:
                  action: define_attribute
                  content_type_path: legal
                  name: summary
                  attribute_type: rich-text
                  description: Long-form human-authored summary text.
                summary: Define a rich text attribute
              RemoveAnAttributeColumn:
                value:
                  action: undefine_attribute
                  content_type_path: legal:contract:nda
                  name: jurisdiction
                summary: Remove an attribute column
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentTypeWrite200Response'
              examples:
                AdoptedLegalSeed:
                  value:
                    content_types:
                    - path: legal
                      code: legal
                      label: Legal
                      children:
                      - path: legal:contract
                        code: contract
                        label: Contract
                  summary: Adopted legal seed
                UpdatedCompanyNode:
                  value:
                    path: compliance:audit-report
                    code: audit-report
                    label: Internal Audit Report
                  summary: Updated company node
          description: 'Action completed: existing node updated or already-present
            attribute replaced'
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentTypeWrite201Response'
              examples:
                NewCompanyNode:
                  value:
                    path: compliance
                    code: compliance
                    label: Compliance
                  summary: New company node
                NewSelectAttribute:
                  value:
                    name: maturity
                    label: Maturity
                    type: select
                    required: false
                    description: ''
                    choices:
                    - Draft
                    - Approved
                    - Deprecated
                  summary: New select attribute
          description: New node or attribute column created
        '204':
          description: Node or attribute deleted (cascade for nodes)
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                AttributeTypeImmutable:
                  value:
                    id: null
                    code: 400
                    error: attribute_type_immutable
                    detail: Cannot change the type of attribute 'jurisdiction' from
                      'text' to 'select'. Delete and recreate the attribute to change
                      its type.
                    doc_url: https://developers.lighton.ai/errors#attribute_type_immutable
                  summary: Attribute type immutable
                AttributeNameReserved:
                  value:
                    id: null
                    code: 400
                    error: attribute_name_reserved
                    detail: '''id'' is a reserved attribute name.'
                    doc_url: https://developers.lighton.ai/errors#attribute_name_reserved
                  summary: Attribute name reserved
                AttributeNameConflict:
                  value:
                    id: null
                    code: 400
                    error: attribute_name_conflict
                    detail: Attribute 'jurisdiction' is already defined on 'legal'
                      in the same tree. Attribute names must be unique across the
                      entire tree.
                    doc_url: https://developers.lighton.ai/errors#attribute_name_conflict
                  summary: Attribute name conflict
                ContentTypeDepthExceeded:
                  value:
                    id: null
                    code: 400
                    error: content_type_depth_exceeded
                    detail: Content type depth would exceed the maximum of 4 levels
                      (got depth 4).
                    doc_url: https://developers.lighton.ai/errors#content_type_depth_exceeded
                  summary: Content type depth exceeded
          description: Invalid request or attribute constraint violated
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                ContentTypeNotFound:
                  value:
                    id: null
                    code: 404
                    error: content_type_not_found
                    detail: Content type 'legal:nonexistent' not found for this company.
                    doc_url: https://developers.lighton.ai/errors#content_type_not_found
                  summary: Content type not found
          description: Parent or target content type not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/content-types/batch:
    post:
      operationId: api_v3_content_types_batch_create
      description: |-
        Execute multiple content-type actions in a single request.

        All actions are **validated upfront** before any execution begins. If any
        action has invalid fields, the entire batch is rejected with a 422 response
        and no actions are executed.

        On **domain errors** (e.g., content type not found, permission denied), the
        batch fails fast at the failing action. The error response includes an
        `"index"` field (0-based) indicating which action caused the failure.
        Actions before the failing index are committed; their results are not
        returned. All verbs are idempotent — it is safe to re-send the entire
        batch after fixing the error.

        **Request:** `{"actions": [<action>, <action>, ...]}`

        Each action object follows the same schema as the single-action
        `POST /api/v3/content-types` endpoint. Maximum 50 actions per batch.

        **Response:** `{"results": [{"status": <code>, "data": <body|null>}, ...]}`

        Results are in the same order as the input actions. The `data` key is
        `null` for 204 actions (deletes).

        See `POST /api/v3/content-types` for available actions and their fields.
      summary: Batch define content types and attributes
      tags:
      - Facets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentTypeBatchRequest'
            examples:
              AdoptAndDefineAttribute:
                value:
                  actions:
                  - action: adopt
                    content_types:
                    - legal
                  - action: define_attribute
                    content_type_path: legal
                    name: owner
                    attribute_type: text
                summary: Adopt and define attribute
              BuildATreeFromScratch:
                value:
                  actions:
                  - action: define_content_type
                    code: compliance
                    label: Compliance
                  - action: define_content_type
                    parent_path: compliance
                    code: audit-report
                    label: Audit Report
                  - action: define_attribute
                    content_type_path: compliance
                    name: auditor
                    attribute_type: text
                summary: Build a tree from scratch
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchResponse'
              examples:
                MixedStatuses:
                  value:
                    results:
                    - status: 200
                      data:
                        content_types:
                        - path: legal
                          code: legal
                          label: Legal
                    - status: 201
                      data:
                        name: owner
                        label: Owner
                        type: text
                        required: false
                        description: ''
                        choices: []
                  summary: Mixed statuses
                DeleteResult(nullData):
                  value:
                    results:
                    - status: 204
                      data: null
                  summary: Delete result (null data)
          description: All actions executed successfully
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3BatchErrorResponse'
              examples:
                ContentTypeNotFound(withIndex):
                  value:
                    id: null
                    code: 404
                    error: content_type_not_found
                    detail: Content type 'nonexistent' not found for this company.
                    doc_url: https://developers.lighton.ai/errors#content_type_not_found
                    index: 1
                  summary: Content type not found (with index)
          description: Domain error with action index
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3BatchErrorResponse'
              examples:
                PermissionDenied(withIndex):
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: Permission denied for action 'undefine_content_type'.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
                    index: 1
                  summary: Permission denied (with index)
          description: Permission denied for action
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/content-types/scope:
    post:
      operationId: api_v3_content_types_scope_create
      description: "Resolves content type and attribute filters from a natural-language\
        \ query.\nCall this **before** `/search`, `/ask`, or `/files` to narrow results\
        \ by domain.\nPass the inferred `content_type` and `attribute` directly to\
        \ those endpoints.\n\nReturns ranked content types grouped by root schema,\
        \ each with a relevance score\nand the attribute definitions available for\
        \ filtering.\n\n### Scores and decision signal\n\nEach content type in the\
        \ response includes a `score` (relevance to your query).\nUse scores to decide\
        \ how to scope your search — higher means stronger match.\n\n`has_signal`\
        \ is a convenience shortcut: it's `true` when the top score meets a\ndefault\
        \ confidence threshold. For custom logic, use `score` directly and apply\n\
        your own threshold via the `threshold` request parameter.\n\n### Three modes\n\
        \n**1. Prompt mode** (default) — returns `prompt_context`, a self-contained\
        \ LLM-ready\ntext block. Feed it to any LLM alongside the user query to infer\
        \ `content_type`\nand `attribute` filters. The prompt includes ranked content\
        \ types, attribute\ndefinitions with filter syntax, inference rules, date\
        \ ranges, and few-shot examples.\n\n**2. Completion mode** — pass `model`\
        \ (technical name) and the API calls the LLM\nfor you. Returns `scope_completion`\
        \ with parsed, normalized filters:\n- Label-to-name mapping (e.g. \"Filing\
        \ Date\" → `filing_date`)\n- Syntax validation against the attribute schema\n\
        - Structured JSON output via guided decoding\n- `warnings` for any normalization\
        \ applied or issues detected\n- If the LLM call fails, `scope_completion`\
        \ is still returned with `warnings`\n  explaining the failure — the rest of\
        \ the response remains usable.\n  \n**3. Catalog + completion mode** — set\
        \ `relevance_scoring: \"none\"` with a `query`\nand `model` to get the full\
        \ content type catalog AND an LLM-inferred\n`scope_completion`. Useful when\
        \ you want the LLM to choose from ALL content types\nwithout retrieval pre-filtering.\
        \ `max_results` and `threshold` are ignored.\n\n### Response fields\n\n| Field\
        \ | Description |\n|-------|-------------|\n| `score` | Relevance score. Higher\
        \ = better match. Comparable across requests. |\n| `max_score` | Highest score\
        \ in a root group. Compare roots without iterating. |\n| `chunk_count` | Retrieval\
        \ chunks matching this CT. More chunks = broader evidence. |\n| `doc_count`\
        \ | Total corpus documents classified under this CT. |\n| `prompt_context`\
        \ | LLM-ready prompt text. Pass to your LLM as-is. |\n| `prompt_version` |\
        \ Fingerprint (`t:<hex>.d:<hex>`) for eval reproducibility. |\n| `scope_completion`\
        \ | Parsed LLM output (only when `model` is provided). |\n\n### Schema context\
        \ mode\n\nOmit `query` to get the full content type catalog — useful for system\
        \ prompts,\ntool descriptions, or schema exploration. `groups` contains all\
        \ content types with\ntheir attributes (`score=0`, `chunk_count=0` since there\
        \ is no query to rank against).\n`prompt_context` contains the same catalog\
        \ as LLM-ready text.\n\n### Integration notes\n\n- Content type paths use\
        \ `:` as separator (e.g. `patent:electricity:h04`).\n- Attribute filter syntax\
        \ is documented in `prompt_context` per attribute type.\n  Date ranges use\
        \ `>=` / `<=` operators (e.g. `filing_date:>=2023-01-01`).\n- Writing meaningful\
        \ attribute descriptions (especially for person-name and\n  code/identifier\
        \ fields) improves the quality of `prompt_context` hints."
      summary: Resolve search scope
      tags:
      - Facets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FacetScopeRequest'
            examples:
              BasicScopeQuery:
                value:
                  query: rejected electronics patents
                summary: Basic scope query
              WithCustomMaxResults:
                value:
                  query: mutual NDA expiring 2025
                  max_results: 5
                summary: With custom max_results
              SchemaContext(noQuery):
                value: {}
                summary: Schema context (no query)
                description: Omit query to get the full CT catalog as prompt_context.
              WithLLMCompletion:
                value:
                  query: patents from Q1 2023
                  model: mistral/mistral-large-latest
                summary: With LLM completion
                description: Pass model to get scope_completion with parsed filters.
              AllCTs+LLMCompletion(noScoring):
                value:
                  query: employment contracts from last year
                  model: mistral/mistral-large-latest
                  relevance_scoring: none
                summary: All CTs + LLM completion (no scoring)
                description: relevance_scoring="none" returns all content types without
                  retrieval ranking, with LLM completion over the full catalog.
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FacetScopeResponse'
              examples:
                StrongMatch—SingleRoot:
                  value:
                    has_signal: true
                    groups:
                    - root: patent
                      root_label: Patent Classification
                      max_score: 1.72
                      content_types:
                      - path: patent:electricity
                        label: Electricity
                        root: patent
                        score: 1.72
                        chunk_count: 12
                        doc_count: 18000
                        attributes:
                        - name: decision
                          label: Decision
                          type: select
                          required: false
                          description: Patent application decision status
                          choices:
                          - Accepted
                          - Rejected
                        - name: filing_date
                          label: Filing Date
                          type: date
                          required: false
                          description: Date the patent application was filed
                          choices: []
                    prompt_context: |-
                      Content types (by relevance):
                        1. Electricity (patent:electricity) — score: 1.72, 12 chunks *

                      Relevant filters:
                        - decision "Decision" (select: Accepted, Rejected)

                      Other available attributes:
                        - filing_date "Filing Date" (date: >=, <=)

                      RULES:
                        1. Use null content_type when the query targets attributes without naming a topic area.
                        ...

                      OUTPUT FORMAT:
                        {"content_type": "<path>" or null, "attribute": [...]}
                    prompt_version: t:a1b2c3d4.d:e5f6a7b8
                  summary: Strong match — single root
                Multi-root—Cross-schemaQuery:
                  value:
                    has_signal: true
                    groups:
                    - root: patent
                      root_label: Patent Classification
                      max_score: 1.72
                      content_types:
                      - path: patent:electricity:h04
                        label: Electric Communication Technique
                        root: patent
                        score: 1.72
                        chunk_count: 8
                        doc_count: 12000
                        attributes:
                        - name: decision
                          label: Decision
                          type: select
                          required: false
                          description: Patent application decision status
                          choices:
                          - Accepted
                          - Rejected
                        - name: filing_date
                          label: Filing Date
                          type: date
                          required: false
                          description: Date the patent application was filed
                          choices: []
                      - path: patent:electricity:h01
                        label: Basic Electric Elements
                        root: patent
                        score: 0.91
                        chunk_count: 3
                        doc_count: 8500
                        attributes:
                        - name: decision
                          label: Decision
                          type: select
                          required: false
                          description: Patent application decision status
                          choices:
                          - Accepted
                          - Rejected
                        - name: filing_date
                          label: Filing Date
                          type: date
                          required: false
                          description: Date the patent application was filed
                          choices: []
                    - root: sic
                      root_label: SIC Industry
                      max_score: 0.45
                      content_types:
                      - path: sic:manufacturing
                        label: Manufacturing
                        root: sic
                        score: 0.45
                        chunk_count: 2
                        doc_count: 3200
                        attributes:
                        - name: industry_code
                          label: Industry Code
                          type: text
                          required: false
                          description: SIC industry classification code
                          choices: []
                    prompt_context: |-
                      Content types (by relevance):
                        1. Electric Communication Technique (patent:electricity:h04) — score: 1.72, 8 chunks *
                        2. Manufacturing (sic:manufacturing) — score: 0.45, 2 chunks
                        ...

                      OUTPUT FORMAT:
                        {"content_type": "<path>" or null, "attribute": [...]}
                    prompt_version: t:a1b2c3d4.d:e5f6a7b8
                  summary: Multi-root — cross-schema query
                LowConfidence—BelowThreshold:
                  value:
                    has_signal: false
                    groups:
                    - root: patent
                      root_label: Patent Classification
                      max_score: 0.42
                      content_types:
                      - path: patent:electricity
                        label: Electricity
                        root: patent
                        score: 0.42
                        chunk_count: 1
                        doc_count: 18000
                        attributes:
                        - name: decision
                          label: Decision
                          type: select
                          required: false
                          description: Patent application decision status
                          choices:
                          - Accepted
                          - Rejected
                        - name: filing_date
                          label: Filing Date
                          type: date
                          required: false
                          description: Date the patent application was filed
                          choices: []
                    prompt_context: |-
                      No confident content type match — query may target metadata (dates, names, codes) rather than a specific domain.
                      Content types (by relevance):
                        1. Electricity (patent:electricity) — score: 0.42, 1 chunks

                      OUTPUT FORMAT:
                        {"content_type": "<path>" or null, "attribute": [...]}
                    prompt_version: t:a1b2c3d4.d:e5f6a7b8
                  summary: Low confidence — below threshold
                  description: has_signal is false when the top score is below the
                    confidence threshold. Groups, attributes, and prompt_context are
                    still returned — use scores to decide whether to apply filters.
                WithScopeCompletion(modelProvided):
                  value:
                    has_signal: true
                    groups:
                    - root: patent
                      root_label: Patent Classification
                      max_score: 1.85
                      content_types:
                      - path: patent:electricity
                        label: Electricity
                        root: patent
                        score: 1.85
                        chunk_count: 15
                        doc_count: 18000
                        attributes:
                        - name: decision
                          label: Decision
                          type: select
                          required: false
                          description: Patent application decision status
                          choices:
                          - Accepted
                          - Rejected
                        - name: filing_date
                          label: Filing Date
                          type: date
                          required: false
                          description: Date the patent application was filed
                          choices: []
                    prompt_context: |-
                      Content types (by relevance):
                        1. Electricity (patent:electricity) — score: 1.85, 15 chunks *

                      Relevant filters:
                        - filing_date "Filing Date" (date: >=, <=)

                      Other available attributes:
                        - decision "Decision" (select: Accepted, Rejected)

                      RULES:
                        ...

                      OUTPUT FORMAT:
                        {"content_type": "<path>" or null, "attribute": [...]}
                    prompt_version: t:a1b2c3d4.d:e5f6a7b8
                    scope_completion:
                      content_type: patent:electricity
                      attribute:
                      - filing_date:>=2023-01-01
                      - filing_date:<=2023-03-31
                      raw_output: '{"content_type":"patent:electricity","attribute":["filing_date:>=2023-01-01","filing_date:<=2023-03-31"]}'
                      normalized: false
                      warnings: []
                  summary: With scope_completion (model provided)
                  description: When model is provided, scope_completion contains parsed
                    filters. scope_completion.content_type and scope_completion.attribute
                    map directly to the search API parameters. raw_output is the LLM's
                    original response. prompt_context is always returned alongside
                    for debugging or fallback.
                SchemaContext(noQuery):
                  value:
                    has_signal: false
                    groups:
                    - root: patent
                      root_label: Patent Classification
                      max_score: 0.0
                      content_types:
                      - path: patent
                        label: Patent
                        root: patent
                        score: 0.0
                        chunk_count: 0
                        doc_count: 20000
                        attributes: []
                      - path: patent:electricity
                        label: Electricity
                        root: patent
                        score: 0.0
                        chunk_count: 0
                        doc_count: 18000
                        attributes:
                        - name: decision
                          label: Decision
                          type: select
                          required: false
                          description: Patent application decision status
                          choices:
                          - Accepted
                          - Rejected
                        - name: filing_date
                          label: Filing Date
                          type: date
                          required: false
                          description: Date the patent application was filed
                          choices: []
                    prompt_context: |-
                      Available content type schemas:

                      Patent Classification (patent):
                        - Electricity (patent:electricity)

                      Attributes:
                        - Decision (select: Accepted, Rejected) on patent:electricity
                        - Filing Date (date) on patent:electricity

                      RULES:
                        ...

                      OUTPUT FORMAT:
                        {"content_type": "<path>" or null, "attribute": [...]}
                  summary: Schema context (no query)
                  description: No query → full CT catalog with attributes. groups
                    contains all content types (score=0, chunk_count=0 since no query
                    to rank). prompt_context contains the same catalog as LLM-ready
                    text.
          description: Scored content types grouped by root.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
          description: Invalid request body.
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/content-types/templates:
    get:
      operationId: api_v3_content_types_templates_retrieve
      description: |-
        Browse the platform's **starter-kit templates** for content types. These are
        ready-made taxonomies (legal, finance, healthcare, tech, manufacturing) you
        can adopt to quickly organise your documents, no manual setup required.

        **Getting started:**
        1. Browse templates here to see what's available
        2. Adopt the ones you need: `POST /api/v3/content-types {"action": "adopt", "paths": ["legal", "finance"]}`
        3. Once adopted, they become **your company's own** content types, fully editable
        4. Customize: rename nodes, add children, define new attributes, or delete what you don't need
        5. Create entirely new content types from scratch with `define_content_type`

        All write operations happen on `POST /api/v3/content-types`. This endpoint
        is read-only: it shows the catalog of available templates.

        **After adoption**, manage your company's content types (adopted + custom)
        via `GET /api/v3/content-types` and `POST /api/v3/content-types`.
        Classify files with `POST /api/v3/files/{id}/facets`.

        **Query modes:**
        - No params → full detail for all templates (children + attributes)
        - `?path=legal` → detail for one template
        - `?path=legal,finance` → detail for multiple (comma-separated)
        - `?path=legal:contract:nda` → detail for a nested node
        - `?depth=0` → root info only (code, label, description, no children/attributes)
        - `?depth=1` → roots + direct children only
        - `?include_attributes=false`: omit attribute definitions for a lighter response

        **Path separator:** `:` (colon). Example: `legal:contract:nda`

        **Attribute inheritance:** Attributes defined at a parent node are inherited
        by all its children. A document classified as `legal:contract:nda` gets
        attributes from `legal`, `legal:contract`, and `legal:contract:nda`.
      summary: List content type templates
      parameters:
      - in: query
        name: depth
        schema:
          type: integer
        description: Tree depth limit. Default (omitted) = full tree. `0` = root info
          only (no children, no attributes). `1` = roots + direct children. `N` =
          N levels of children.
      - in: query
        name: include_attributes
        schema:
          type: boolean
        description: 'Include attribute definitions per content type node. Default:
          true.'
      - in: query
        name: path
        schema:
          type: string
        description: 'Content type path(s), colon-separated hierarchy. Comma-separated
          for multiple (e.g., `?path=legal,finance`, `?path=tech,manufacturing`, or
          `?path=legal:contract:nda`). Root codes: finance, healthcare, legal, manufacturing,
          tech'
        examples:
          LegalRoot:
            value: legal
            summary: Legal root
            description: Get the full legal content type tree
          HealthcareRoot:
            value: healthcare
            summary: Healthcare root
            description: Get the full healthcare content type tree
          FinanceRoot:
            value: finance
            summary: Finance root
            description: Get the full finance content type tree
          TechRoot:
            value: tech
            summary: Tech root
            description: Get the full tech content type tree
          ManufacturingRoot:
            value: manufacturing
            summary: Manufacturing root
            description: Get the full manufacturing content type tree
          NestedNode:
            value: legal:contract:nda
            summary: Nested node
            description: Get detail for a specific leaf node
      tags:
      - Facets
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemplateListResponse'
              examples:
                FullDetail(default,NoParams):
                  value:
                    content_types:
                    - path: legal
                      code: legal
                      label: Legal
                      description: 'Legal documents: contracts, litigation, compliance,
                        opinions, and filings.'
                      children:
                      - code: contract
                        label: Contract
                        description: 'Binding agreements between parties: NDAs, SLAs,
                          MSAs, employment, and licensing.'
                        path: legal:contract
                        children:
                        - code: nda
                          label: Non-Disclosure Agreement
                          description: ''
                          path: legal:contract:nda
                        - code: sla
                          label: Service Level Agreement
                          description: ''
                          path: legal:contract:sla
                      - code: litigation
                        label: Litigation
                        description: 'Court proceedings: briefs, motions, depositions,
                          and court orders.'
                        path: legal:litigation
                        children:
                        - code: brief
                          label: Legal Brief
                          description: ''
                          path: legal:litigation:brief
                      attributes:
                        legal:
                        - name: jurisdiction
                          label: Jurisdiction
                          type: multi-select
                          required: false
                          description: Legal jurisdiction(s) governing the document
                          choices:
                          - FR
                          - US
                          - UK
                          - DE
                          - CH
                        - name: confidentiality_level
                          label: Confidentiality Level
                          type: select
                          required: false
                          choices:
                          - Public
                          - Internal
                          - Confidential
                          - Strictly Confidential
                        legal:contract:
                        - name: contract_value
                          label: Contract Value
                          type: number
                          required: false
                          description: Total monetary value of the contract
                        - name: effective_date
                          label: Effective Date
                          type: date
                          required: false
                        legal:contract:nda:
                        - name: counterparty
                          label: Counterparty
                          type: text
                          required: true
                          description: Name of the other party to the NDA
                        - name: is_mutual
                          label: Is Mutual
                          type: boolean
                          required: false
                          description: Whether the NDA applies symmetrically to both
                            parties
                  summary: Full detail (default, no params)
                  description: 'Default response: all root content types with children
                    and attributes'
                RootsOnly(?depth=0):
                  value:
                    content_types:
                    - path: legal
                      code: legal
                      label: Legal
                      description: 'Legal documents: contracts, litigation, compliance,
                        opinions, and filings.'
                    - path: healthcare
                      code: healthcare
                      label: Healthcare
                      description: 'Healthcare documents: clinical, administrative,
                        billing, research, and operations.'
                    - path: finance
                      code: finance
                      label: Finance
                      description: 'Financial documents: reporting, audit, treasury,
                        tax, and planning.'
                    - path: tech
                      code: tech
                      label: Technology
                      description: 'Technology documents: specifications, documentation,
                        operations, security, and architecture.'
                    - path: manufacturing
                      code: manufacturing
                      label: Manufacturing
                      description: 'Manufacturing documents: production, quality,
                        maintenance, and supply chain.'
                  summary: Roots only (?depth=0)
                  description: 'Minimal response: code, label, description only. No
                    children or attributes.'
          description: Content types returned successfully
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                UnknownPath:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: 'Content type path(s) not found: unknown'
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Unknown path
          description: Content type path(s) not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files/{file_id}/facets:
    get:
      operationId: api_v3_files_facets_retrieve
      description: |-
        See what content types a file is classified under and what attribute values
        have been set on it.

        A file can be classified under **multiple content types** (e.g., both
        `legal:contract:nda` and `compliance:audit-report`). Each classification
        comes with its own set of **attribute values**, the metadata fields defined
        in your content-type schema.

        **Response structure:**

        Each content type entry includes:
        - `path`: the content type (e.g., `legal:contract:nda`)
        - `label`: human-readable name
        - `labels`: breadcrumb from root to leaf (`["Legal", "Contract", "NDA"]`)

        Each attribute value includes:
        - `name` / `label`: identifier and display name
        - `value`: the current value (shape depends on type)
        - `type`: the attribute type (`text`, `number`, `date`, `boolean`, `select`, `multi-select`)
        - `choices`: available options for `select` / `multi-select`
        - `required`: whether the attribute is required by the schema

        The response includes `can_edit`, which indicates whether you have permission
        to modify this file's classifications and attribute values.

        **To modify:** use `POST /api/v3/files/{file_id}/facets` to classify,
        set attribute values, or remove classifications.

        **To set up content types first:** see `GET /api/v3/content-types/templates`
        (browse starter templates) and `POST /api/v3/content-types` (adopt or create).
      summary: List file classifications and attribute values
      parameters:
      - in: path
        name: file_id
        schema:
          type: integer
        required: true
      tags:
      - Facets
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentAttributesListResponse'
          description: ''
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: Document not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not found
          description: File not found or not accessible
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    post:
      operationId: api_v3_files_facets_create
      description: |-
        Apply content-type classifications to a file and set attribute values
        (metadata) on it. This is how you tag a document with structured metadata
        from your content-type schema.

        **Typical workflow:**
        1. **Classify** the file: `{"action": "classify",
           "content_type_path": "legal:contract:nda"}`
        2. **Set attribute values**: `{"action": "set_value",
           "content_type_path": "legal:contract:nda",
           "attribute_name": "jurisdiction", "value": ["FR", "DE"]}`
        3. **Read back** with `GET /api/v3/files/{file_id}/facets`

        A file can be classified under **multiple content types**. Just call
        `classify` for each one. Removing a classification (`unclassify`) cascades:
        all attribute values under that content type are removed too.

        **Actions:**
        - `classify`: assign a content type to the file (idempotent)
        - `unclassify`: remove a content type and all its attribute values
        - `set_value`: set or update an attribute value (the content type must be classified first)
        - `clear_value`: remove an attribute value

        **Value types for `set_value`:**
        - `text` / `rich-text` → string
        - `number` → number or numeric string
        - `date` → date string, normalized to `YYYY-MM-DD`
        - `boolean` → `true` / `false`
        - `select` → one string from `choices`
        - `multi-select` → array of strings from `choices`

        To clear a value, use `clear_value` (not `set_value` with `null`).

        **Prerequisites:** Content types must be set up first. See
        `GET /api/v3/content-types/templates` (browse templates) and
        `POST /api/v3/content-types` (adopt or create).

        Requires edit access to the file.
      summary: Classify file and set attribute values
      parameters:
      - in: path
        name: file_id
        schema:
          type: integer
        required: true
      tags:
      - Facets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileFacetActionRequest'
            examples:
              ClassifyFile:
                value:
                  action: classify
                  content_type_path: legal:contract:nda
                summary: Classify file
              SetTextValue:
                value:
                  action: set_value
                  content_type_path: legal:contract:nda
                  attribute_name: counterparty
                  value: Nimbus Labs
                summary: Set text value
              SetNumberValue:
                value:
                  action: set_value
                  content_type_path: finance:report
                  attribute_name: contract_value
                  value: 50000
                summary: Set number value
              SetDateValue:
                value:
                  action: set_value
                  content_type_path: legal:contract
                  attribute_name: effective_date
                  value: '2024-06-30'
                summary: Set date value
              SetBooleanValue:
                value:
                  action: set_value
                  content_type_path: legal:contract:nda
                  attribute_name: is_mutual
                  value: true
                summary: Set boolean value
              SetSelectValue:
                value:
                  action: set_value
                  content_type_path: tech:specification
                  attribute_name: maturity
                  value: Approved
                summary: Set select value
              SetMulti-selectValue:
                value:
                  action: set_value
                  content_type_path: legal:contract:nda
                  attribute_name: jurisdiction
                  value:
                  - FR
                  - DE
                summary: Set multi-select value
              ClearValue:
                value:
                  action: clear_value
                  content_type_path: legal:contract:nda
                  attribute_name: jurisdiction
                summary: Clear value
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileFacetWriteResponse'
          description: Content type already classified, or attribute value updated
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileFacetWriteResponse'
              examples:
                ContentTypeClassified:
                  value:
                    content_type_path: legal:contract:nda
                    label: Non-Disclosure Agreement
                  summary: Content type classified
                AttributeValueCreated:
                  value:
                    name: jurisdiction
                    value:
                    - FR
                    - DE
                    content_type_path: legal:contract:nda
                  summary: Attribute value created
                BooleanValueSet:
                  value:
                    name: is_mutual
                    value: true
                    content_type_path: legal:contract:nda
                  summary: Boolean value set
          description: Content type classified or attribute value created
        '204':
          description: Content type unclassified or attribute value cleared
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                AttributeValueInvalid:
                  value:
                    id: null
                    code: 400
                    error: attribute_value_invalid
                    detail: 'jurisdiction: expected list, got str'
                    doc_url: https://developers.lighton.ai/errors#attribute_value_invalid
                  summary: Attribute value invalid
                UnknownContentType:
                  value:
                    id: null
                    code: 400
                    error: content_type_unknown
                    detail: 'Unknown content type path: ''fake:path''.'
                    doc_url: https://developers.lighton.ai/errors#content_type_unknown
                  summary: Unknown content type
                SiblingConflict:
                  value:
                    id: null
                    code: 400
                    error: content_type_sibling_conflict
                    detail: Document already has content type 'legal:contract' from
                      the same tree. Unclassify it before assigning 'legal:compliance'.
                    doc_url: https://developers.lighton.ai/errors#content_type_sibling_conflict
                  summary: Sibling conflict
          description: Validation error or business rule violation
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to edit this file's facets.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: No edit permission
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                ContentTypeNotAssigned:
                  value:
                    id: null
                    code: 404
                    error: content_type_not_assigned
                    detail: Content type 'legal:contract' not assigned to document.
                    doc_url: https://developers.lighton.ai/errors#content_type_not_assigned
                  summary: Content type not assigned
          description: File or content type not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/files/{file_id}/facets/batch:
    post:
      operationId: api_v3_files_facets_batch_create
      description: |-
        Execute multiple file facet actions in a single request.

        All actions are **validated upfront** before any execution begins. If any
        action has invalid fields, the entire batch is rejected with a 422 response
        and no actions are executed.

        On **domain errors** (e.g., unknown content type, sibling conflict), the
        batch fails fast at the failing action. The error response includes an
        `"index"` field (0-based) indicating which action caused the failure.
        Actions before the failing index are committed; their results are not
        returned. All verbs are idempotent — it is safe to re-send the entire
        batch after fixing the error.

        **Request:** `{"actions": [<action>, <action>, ...]}`

        Each action object follows the same schema as the single-action
        `POST /api/v3/files/{file_id}/facets` endpoint. Maximum 50 actions per batch.

        **Response:** `{"results": [{"status": <code>, "data": <body|null>}, ...]}`

        Results are in the same order as the input actions. The `data` key is
        `null` for 204 actions (unclassify, clear_value).

        See `POST /api/v3/files/{file_id}/facets` for available actions and their fields.

        Requires edit access to the file.
      summary: Batch classify and set attribute values
      parameters:
      - in: path
        name: file_id
        schema:
          type: integer
        required: true
      tags:
      - Facets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileFacetBatchRequest'
            examples:
              ClassifyAndSetAttributes:
                value:
                  actions:
                  - action: classify
                    content_type_path: legal:contract:nda
                  - action: set_value
                    content_type_path: legal:contract:nda
                    attribute_name: jurisdiction
                    value:
                    - FR
                    - DE
                  - action: set_value
                    content_type_path: legal:contract:nda
                    attribute_name: counterparty
                    value: Nimbus Labs
                summary: Classify and set attributes
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchResponse'
              examples:
                Classify+SetValues:
                  value:
                    results:
                    - status: 201
                      data:
                        content_type_path: legal:contract:nda
                        label: Non-Disclosure Agreement
                    - status: 201
                      data:
                        name: jurisdiction
                        value:
                        - FR
                        - DE
                        content_type_path: legal:contract:nda
                    - status: 201
                      data:
                        name: counterparty
                        value: Nimbus Labs
                        content_type_path: legal:contract:nda
                  summary: Classify + set values
          description: All actions executed successfully
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3BatchErrorResponse'
              examples:
                UnknownContentType(withIndex):
                  value:
                    id: null
                    code: 400
                    error: content_type_unknown
                    detail: 'Unknown content type path: ''fake:path''.'
                    doc_url: https://developers.lighton.ai/errors#content_type_unknown
                    index: 1
                  summary: Unknown content type (with index)
          description: Domain error with action index
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3BatchErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: Document not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not found
          description: File not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/tags:
    get:
      operationId: api_v3_tags_list
      description: |-
        Retrieve a list of tags for the authenticated user's company.
        Results are ordered by creation date (newest first).
      summary: List all tags for the authenticated user's company
      parameters:
      - in: query
        name: auto_assign
        schema:
          type: boolean
        description: Filter by auto_assign flag. True if the tag can be automatically
          assigned by the system, False if it can only be assigned manually.
      - in: query
        name: name
        schema:
          type: string
        description: Filter by tag name (case-insensitive partial match)
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      tags:
      - Tags
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTagListResponseSerializerV3List'
              examples:
                ListOfTags:
                  value:
                    count: 123
                    next: http://api.example.org/accounts/?page=4
                    previous: http://api.example.org/accounts/?page=2
                    results:
                    - - id: 1
                        created_at: '2024-01-15T10:30:00Z'
                        updated_at: '2024-01-15T10:30:00Z'
                        name: Report
                        description: Documents summarizing exchanges, meetings notes,
                          transcripts.
                        auto_assign: true
                        document_count: 15
                      - id: 2
                        created_at: '2024-01-14T09:00:00Z'
                        updated_at: '2024-01-14T09:00:00Z'
                        name: Product
                        description: Product management docs. Design, strategy, roadmaps,
                          release notes.
                        auto_assign: false
                        document_count: 8
                  summary: List of tags
          description: List of tags for the authenticated user's company
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InternalServerError:
                  value:
                    id: null
                    code: 500
                    error: internal_server_error
                    detail: An unexpected error occurred. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#internal_server_error
                  summary: Internal Server Error
          description: An unexpected error occurred
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    post:
      operationId: api_v3_tags_create
      description: |-
        Create a new tag for the authenticated user's company.
        The auto_assign flag determines if the tag can be automatically assigned by the system (True)
        or only manually (False).
        Requires tag creation permission.
      summary: Create a new tag for the company
      tags:
      - Tags
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TagCreateRequestSerializerV3'
            examples:
              CreateTagRequest:
                value:
                  name: Project Alpha
                  description: Documents related to the development and release of
                    Project Alpha
                  auto_assign: true
                summary: Create tag request
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TagCreateRequestSerializerV3'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TagCreateRequestSerializerV3'
        required: true
      security:
      - bearerAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TagListResponseSerializerV3'
              examples:
                CreatedTag:
                  value:
                    id: 3
                    created_at: '2024-01-16T11:00:00Z'
                    updated_at: '2024-01-16T11:00:00Z'
                    name: Project Alpha
                    description: Documents related to the development and release
                      of Project Alpha
                    auto_assign: true
                    document_count: 0
                  summary: Created tag
          description: Tag created successfully
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InternalServerError:
                  value:
                    id: null
                    code: 500
                    error: internal_server_error
                    detail: An unexpected error occurred. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#internal_server_error
                  summary: Internal Server Error
          description: An unexpected error occurred
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/tags/{id}:
    delete:
      operationId: api_v3_tags_destroy
      description: |-
        Delete a company tag.
        This will also remove all Document-Tag associations with this tag.
        Requires tag deletion permission.
      summary: Delete a company tag
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this Tag.
        required: true
      tags:
      - Tags
      security:
      - bearerAuth: []
      responses:
        '204':
          description: Tag deleted successfully. All Document-Tag associations have
            been removed.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                InternalServerError:
                  value:
                    id: null
                    code: 500
                    error: internal_server_error
                    detail: An unexpected error occurred. Please try again later.
                    doc_url: https://developers.lighton.ai/errors#internal_server_error
                  summary: Internal Server Error
          description: An unexpected error occurred
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/workspaces:
    get:
      operationId: api_v3_workspaces_list
      description: |-
        ⚠️ **ALPHA ENDPOINT** - This endpoint is in alpha and subject to breaking changes. Use with caution in production environments.

        Get the list of accessible workspaces for the authenticated user. Returns workspaces where the user is set as member (through any group: private, company, or custom). Please use instance or company level endpoints to access the workspaces as admin.

        **Filtering:** All users see only workspaces where they are members. Admin users should use `/api/v3/instance/workspaces` or `/api/v3/company/workspaces` for administrative access.

        Supported query filters: `workspace_type`, `document_upload_method`, `datasource_type` (`googledrive`, `sharepoint`, `servicenow`, `webscrapper`), `name` (case-insensitive contains), `group_id`, `group_name`, `user_role`.

        **API keys:** `scoped_api_keys` lists your own non-revoked keys that can access the workspace. Each entry has a `scope_type`: `workspace` for keys explicitly scoped to it (listed first, with their per-workspace role), or `global` for keys with no scope rows that implicitly reach every workspace (their `role` mirrors your own role on the workspace).

        **Taxonomy:** Each workspace includes a `taxonomy` field summarizing content type classification. `classified_files_rate` is the proportion of documents with at least one content type (0-to-1 ratio). `root_content_types` lists top-level content type families with document counts. A workspace holding documents that are all unclassified reports a rate of `0.0` with an empty `root_content_types`; the whole `taxonomy` object is `null` only when the workspace has no documents.

        Results ordered by creation date (newest first), paginated with 20 elements per page by default.
      summary: List workspaces
      parameters:
      - in: query
        name: datasource_type
        schema:
          type: string
          enum:
          - googledrive
          - servicenow
          - sharepoint
          - webscrapper
        description: |-
          The type of data source.

          * `servicenow` - ServiceNow
          * `googledrive` - Google Drive
          * `sharepoint` - SharePoint
          * `webscrapper` - WebScrapper
      - in: query
        name: document_upload_method
        schema:
          type: string
          enum:
          - manual
          - synced
        description: |-
          Method for adding documents to this workspace: manual uploads or synced from datasources

          * `manual` - Manual
          * `synced` - Synced
      - in: query
        name: group_id
        schema:
          type: integer
      - in: query
        name: group_name
        schema:
          type: string
      - in: query
        name: name
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      - in: query
        name: user_role
        schema:
          type: string
          enum:
          - editor
          - owner
          - viewer
        description: |-
          * `owner` - Owner
          * `editor` - Editor
          * `viewer` - Viewer
      - in: query
        name: workspace_type
        schema:
          type: string
          enum:
          - personal
          - public
          - shared
        description: |-
          * `shared` - Shared
          * `personal` - Personal
          * `public` - Public
      tags:
      - Workspaces
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedStandardWorkspaceV3ListResponseList'
          description: List of workspaces where the user is a member
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '401':
          description: Unauthenticated - Missing or invalid API key/session cookie
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    post:
      operationId: api_v3_workspaces_create
      description: |-
        ⚠️ **ALPHA ENDPOINT** - This endpoint is in alpha and subject to breaking changes. Use with caution in production environments.

        Create a new custom workspace in the authenticated user's company. Requires the company to have `allow_user_workspace_creation` enabled, unless the caller is a company or instance administrator (who may always create workspaces). Returns **403** if workspace creation is disabled for the company and the caller is not an administrator.

        The creator is automatically added as OWNER.
      summary: Create a workspace
      tags:
      - Workspaces
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StandardWorkspaceCreateV3Request'
            examples:
              CreateWorkspace:
                value:
                  name: Engineering Team Workspace
                  description: Workspace for the engineering team
                summary: Create workspace
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/StandardWorkspaceCreateV3Request'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/StandardWorkspaceCreateV3Request'
        required: true
      security:
      - bearerAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StandardWorkspaceV3DetailsResponse'
          description: Workspace created successfully
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '401':
          description: Unauthenticated - Missing or invalid API key/session cookie
        '403':
          description: Unauthorized - Standard users of this company are not allowed
            to create workspaces
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/workspaces/datasource/browse:
    post:
      operationId: api_v3_workspaces_datasource_browse_create
      description: |-
        ⚠️ **ALPHA ENDPOINT** - This endpoint is in alpha and subject to breaking changes. Use with caution in production environments.

        Browse the remote folder hierarchy of a datasource without persisting anything.

        Connects to the external provider using the credentials in the payload and returns the immediate subfolders of ``parent_id`` (or the top-level entries when ``parent_id`` is ``null``). Use this to power a visual folder picker before submitting a datasource configuration via `PATCH /api/v3/workspaces/{id}` with a `datasource` payload.

        **Access:** any authenticated user.

        Supported providers and credentials:
        - **googledrive**: `service_account_file` (JSON string of the service account key file). When ``parent_id`` is omitted, returns the folders explicitly shared with the service account.
        - **sharepoint**: `client_id`, `client_secret`, `tenant_id`, `instance_url`, `site_name`. When both ``drive_id`` and ``parent_id`` are ``null``, returns the site's document libraries as ``kind="library"`` entries (each entry's ``id`` is the drive id). Pass that ``id`` back as ``drive_id`` (with ``parent_id=null``) to list the library root; pass it as ``drive_id`` together with a folder's ``id`` as ``parent_id`` to descend into a folder.
      summary: Browse datasource folders
      tags:
      - Workspaces
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkspaceDatasourceBrowseV3Request'
            examples:
              SharePoint—ListDocumentLibraries(root):
                value:
                  type: sharepoint
                  credentials:
                    tenant_id: tenant-uuid
                    client_id: client-uuid
                    client_secret: secret
                    instance_url: https://contoso.sharepoint.com
                    site_name: Engineering
                  drive_id: null
                  parent_id: null
                summary: SharePoint — list document libraries (root)
              SharePoint—ListFoldersInsideALibrary:
                value:
                  type: sharepoint
                  credentials:
                    tenant_id: tenant-uuid
                    client_id: client-uuid
                    client_secret: secret
                    instance_url: https://contoso.sharepoint.com
                    site_name: Engineering
                  drive_id: b!abc
                  parent_id: null
                summary: SharePoint — list folders inside a library
              GoogleDrive—ChildrenOfAFolder:
                value:
                  type: googledrive
                  credentials:
                    service_account_file: '{"type":"service_account", "...": "..."}'
                  parent_id: 0AAbCdEfGhIjKlMn
                summary: Google Drive — children of a folder
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/WorkspaceDatasourceBrowseV3Request'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/WorkspaceDatasourceBrowseV3Request'
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkspaceDatasourceBrowseV3Response'
              examples:
                Response—SharePointDocumentLibraries:
                  value:
                    folders:
                    - id: b!abc
                      name: Documents
                      has_children: true
                      path: Documents
                      drive_id: null
                      kind: library
                    - id: b!def
                      name: SyncedWithParadigm
                      has_children: true
                      path: SyncedWithParadigm
                      drive_id: null
                      kind: library
                  summary: Response — SharePoint document libraries
                Response—SharePointFoldersInsideALibrary:
                  value:
                    folders:
                    - id: 01ABC
                      name: Engineering
                      has_children: true
                      path: /Engineering
                      drive_id: b!abc
                      kind: folder
                    - id: 01DEF
                      name: Templates
                      has_children: false
                      path: /Templates
                      drive_id: b!abc
                      kind: folder
                  summary: Response — SharePoint folders inside a library
          description: Folder listing
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
          description: Bad Request - Invalid credentials or connection failure to
            the external datasource
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/workspaces/datasource/test:
    post:
      operationId: api_v3_workspaces_datasource_test_create
      description: |-
        ⚠️ **ALPHA ENDPOINT** - This endpoint is in alpha and subject to breaking changes. Use with caution in production environments.

        Test datasource credentials without persisting anything.

        Validates that the provided credentials can connect to the external source. Succeeds when the connection can be established; returns an error otherwise. No datasource or import is created. Use this before `PATCH /api/v3/workspaces/{id}` with a `datasource` payload to surface connection errors before committing the conversion.

        **Access:** any authenticated user.

        Credentials per type:
        - **googledrive**: `service_account_file` (JSON string of the service account key file)
        - **sharepoint**: `client_id`, `client_secret`, `tenant_id`, `site_id` (optional), `site_name` (optional)
        - **servicenow**: `instance_url`, `username`, `password`
        - **webscrapper**: no credentials required

        Filter criteria per type:
        - **googledrive**: `folder_id` (required), `recursive` (optional)
        - **sharepoint**: `folder_path` (required), `recursive` (optional)
        - **servicenow**: `doc_type` (required, e.g. `knowledge`)
        - **webscrapper**: `start_url` (required)
      summary: Test datasource credentials
      tags:
      - Workspaces
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StandardWorkspaceDatasourceV3Request'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/StandardWorkspaceDatasourceV3Request'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/StandardWorkspaceDatasourceV3Request'
        required: true
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Connection successful
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
          description: Bad Request - Invalid credentials or connection failure to
            the external datasource
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/workspaces/{id}:
    get:
      operationId: api_v3_workspaces_retrieve
      description: |-
        ⚠️ **ALPHA ENDPOINT** - This endpoint is in alpha and subject to breaking changes. Use with caution in production environments.

        Retrieve a workspace by ID. Returns workspace in V3 format.

        **Access:** Instance-level users (Sys Admin, Account Manager, Admin, DPO Admin) can retrieve any workspace. Company-level users (Company Admin, Company DPO) can retrieve workspaces in their company. Regular users can retrieve workspaces where they are members.

        **Member Visibility:** Instance-level users and company-level users see all members. Workspace OWNER sees members. EDITOR and VIEWER do not see members.

        **Sync status:** For synced workspaces, the response includes a `sync` block with `datasource_type`, `source_name`, `last_status`, `updated_at`, `failed_files_count`, and `next_import_date`. Use this field for polling the sync state.

        Non-existent and unauthorized workspaces are treated identically (existence is not disclosed).
      summary: Retrieve a workspace
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: The unique identifier of the workspace.
        required: true
      tags:
      - Workspaces
      security:
      - bearerAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StandardWorkspaceV3DetailsResponse'
          description: Workspace details retrieved successfully
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    patch:
      operationId: api_v3_workspaces_partial_update
      description: |-
        ⚠️ **ALPHA ENDPOINT** - This endpoint is in alpha and subject to breaking changes. Use with caution in production environments.

        Partially update a given workspace.

        **Standard update (workspace OWNER only):**
        - **name** (string, optional): Desired workspace name (max 100 characters, cannot be empty)
        - **description** (string, optional): Desired workspace description. Send empty string or null to clear.

        **Convert to a synced workspace** (workspace OWNER or a role granting workspace edit/delete):
        - **datasource** (object): Datasource configuration used to populate the workspace. Credentials are validated against the external source before persistence; use `POST /api/v3/workspaces/{id}/datasource/test` to validate them without committing.
        - The target workspace must be empty (no documents) and not already synced.

        **Edit an existing synced workspace's datasource:**
        - If the workspace is already synced and no successful sync has happened yet, sending a `datasource` payload edits the datasource in place (full credential re-entry required, name/filter_criteria updated, next sync re-triggered).
        - After the first successful sync, the field is rejected with **409 Conflict** — ingested data integrity is preserved by locking the config. Delete and recreate the workspace to change its configuration.
        - The datasource `type` is immutable on edit.
        - Edits are also rejected with 409 while a sync is currently in flight (WAITING/PROCESSING).
        - The current edit-availability is exposed in the response under `sync.editable` (boolean).

        **Restrictions:**
        - Only SHARED workspaces can be updated (PERSONAL workspaces cannot be modified)
        - Conversion is one-way: a synced workspace cannot be reverted to manual via the API
      summary: Update a workspace
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: The unique identifier of the workspace.
        required: true
      tags:
      - Workspaces
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedUpdateWorkspaceV3Request'
            examples:
              RenameWorkspace:
                value:
                  name: Updated Workspace Name
                  description: Updated description
                summary: Rename workspace
              RestoreASoft-deletedWorkspace:
                value:
                  deleted_at: null
                summary: Restore a soft-deleted workspace
              RestoreUnderANewName(resolvesANameCollision):
                value:
                  deleted_at: null
                  name: Project Apollo (restored)
                summary: Restore under a new name (resolves a name collision)
              RestoreAndUpdateTheDescription:
                value:
                  deleted_at: null
                  description: Reinstated after review
                summary: Restore and update the description
              ConvertToServiceNowSyncedWorkspace:
                value:
                  datasource:
                    type: servicenow
                    name: My ServiceNow KB
                    credentials:
                      instance_url: https://acme.service-now.com
                      username: admin
                      password: s3cr3t
                    filter_criteria:
                      doc_type: knowledge
                summary: Convert to ServiceNow synced workspace
              ConvertToGoogleDriveSyncedWorkspace:
                value:
                  datasource:
                    type: googledrive
                    name: Meet Recordings
                    credentials:
                      service_account_file: '{"type":"service_account","project_id":"my-project",...}'
                    filter_criteria:
                      folder_id: 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs
                      recursive: true
                summary: Convert to Google Drive synced workspace
              ConvertToSharePointSyncedWorkspace:
                value:
                  datasource:
                    type: sharepoint
                    name: Engineering Docs
                    credentials:
                      client_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                      client_secret: s3cr3t
                      tenant_id: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
                      site_name: EngineeringSite
                    filter_criteria:
                      folder_path: /Shared Documents/Engineering
                      recursive: true
                summary: Convert to SharePoint synced workspace
              ConvertToWebScrapperSyncedWorkspace:
                value:
                  datasource:
                    type: webscrapper
                    name: Public Docs
                    credentials: {}
                    filter_criteria:
                      start_url: https://docs.example.com
                summary: Convert to WebScrapper synced workspace
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedUpdateWorkspaceV3Request'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedUpdateWorkspaceV3Request'
      security:
      - bearerAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StandardWorkspaceV3DetailsResponse'
          description: Workspace updated successfully
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
          description: Conflict - Datasource edit rejected because the workspace has
            already completed at least one successful sync (config locked), or a sync
            is currently in flight.
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    delete:
      operationId: api_v3_workspaces_destroy
      description: |-
        ⚠️ **ALPHA ENDPOINT** - This endpoint is in alpha and subject to breaking changes. Use with caution in production environments.

        Soft-delete a custom workspace you own.

        The workspace and its memberships are marked as deleted but retained for the configured recovery period; collection data (documents, chunks, embeddings) is preserved until the workspace is permanently deleted by the cleanup task. The workspace can be restored within the recovery period via `PATCH` with `deleted_at=null` (use `?include_deleted=true` to address it after deletion).

        **Restrictions:**
        - PERSONAL workspaces cannot be deleted (system-managed)
        - Caller must be an OWNER of the workspace (or hold instance/company workspace-delete permission)
      summary: Delete a workspace
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: The unique identifier of the workspace.
        required: true
      tags:
      - Workspaces
      security:
      - bearerAuth: []
      - {}
      responses:
        '204':
          description: Workspace soft-deleted
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Forbidden:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: You do not have permission to perform this action.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
          description: Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/keys:
    get:
      operationId: api_v3_keys_list
      description: |-
        List all API keys belonging to the authenticated user.

        Each entry exposes its workspace scope via `scopes`. Every scope entry carries a `scope_type`:
        - `workspace` — the key is explicitly scoped to that workspace, with its own per-workspace permission (`viewer`, `editor`, or `owner`).
        - `global` — the key has no explicit scope rows and reaches every workspace you can access; `scopes` then lists those workspaces with your own current role on each (the effective access ceiling). A global key never mixes the two types.
      summary: List API keys
      parameters:
      - in: query
        name: is_expired
        schema:
          type: boolean
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      tags:
      - API Keys
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAPIKeyV3ResponseList'
          description: Paginated list of API keys belonging to the authenticated user.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    post:
      operationId: api_v3_keys_create
      description: |-
        Create a new API key for the authenticated user.

        **The full key value is returned only once** in the creation response and cannot be retrieved again afterwards.

        `expires_at` is required:
        - A future datetime expires the key at that time.
        - `null` creates a key that never expires.

        **Workspace scoping (optional):** include `scopes` — a list of `{workspace_id, permission}` entries — to restrict the key to those workspaces. Each entry's `permission` is one of `viewer`, `editor`, or `owner`, and cannot exceed the role you currently hold on that workspace. Different scopes on the same key can carry different permissions.
      summary: Create API key
      tags:
      - API Keys
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAPIKeyV3Request'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/CreateAPIKeyV3Request'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/CreateAPIKeyV3Request'
        required: true
      security:
      - bearerAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateAPIKeyV3Response'
          description: API key created. The `key` field contains the full key value
            — save it now, it will not be shown again.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                QuotaExceeded:
                  value:
                    id: null
                    code: 400
                    error: bad_request
                    detail: You have reached the maximum allowed number of api keys.
                      Think about deleting some to create new ones.
                    doc_url: https://developers.lighton.ai/errors#bad_request
                  summary: Quota exceeded
          description: Bad Request — API key quota exceeded (domain limit).
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
  /api/v3/keys/{id}:
    get:
      operationId: api_v3_keys_retrieve
      description: Retrieve a single API key belonging to the authenticated user,
        including its workspace scope.
      summary: Retrieve API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
        required: true
      tags:
      - API Keys
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyV3Response'
          description: The requested API key.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    patch:
      operationId: api_v3_keys_partial_update
      description: |-
        Update an existing API key.

        Supports renaming and replacing the workspace scope:
        - Pass `scopes` with a non-empty list of `{workspace_id, permission}` entries to replace the full scope set. Existing scope rows not in the new list are dropped.
        - Pass `scopes: []` to unscope the key entirely.
        - The permission ceiling on each scoped workspace is re-validated against your current role there.
      summary: Update API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
        required: true
      tags:
      - API Keys
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedUpdateAPIKeyV3Request'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedUpdateAPIKeyV3Request'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedUpdateAPIKeyV3Request'
      security:
      - bearerAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyV3Response'
          description: The updated API key.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                BadRequest:
                  value:
                    id: null
                    code: 400
                    error: bad_request
                    detail: The request body could not be parsed as valid JSON.
                    doc_url: https://developers.lighton.ai/errors#bad_request
                  summary: Bad Request
          description: Request body is not valid JSON
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ValidationErrorResponse'
              examples:
                ValidationError:
                  value:
                    id: null
                    code: 422
                    error: validation_error
                    detail: One or more fields failed validation.
                    doc_url: https://developers.lighton.ai/errors#validation_error
                    fields:
                      <field_name>:
                      - error: required
                        detail: This field is required.
                  summary: Validation Error
          description: Request body is valid JSON but one or more fields failed validation
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
    delete:
      operationId: api_v3_keys_destroy
      description: Revoke an API key. Revoked keys can no longer be used to authenticate
        requests.
      summary: Revoke API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
        required: true
      tags:
      - API Keys
      security:
      - bearerAuth: []
      responses:
        '204':
          description: API key revoked successfully.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                Unauthorized:
                  value:
                    id: null
                    code: 401
                    error: unauthorized
                    detail: Authentication credentials were not provided or are invalid.
                    doc_url: https://developers.lighton.ai/errors#unauthorized
          description: Authentication credentials were not provided or are invalid
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                AlreadyRevoked:
                  value:
                    id: null
                    code: 403
                    error: insufficient_permissions
                    detail: This API key has already been revoked.
                    doc_url: https://developers.lighton.ai/errors#insufficient_permissions
                  summary: Already revoked
          description: Forbidden — the API key has already been revoked.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIV3ErrorResponse'
              examples:
                NotFound:
                  value:
                    id: null
                    code: 404
                    error: not_found
                    detail: The requested resource was not found.
                    doc_url: https://developers.lighton.ai/errors#not_found
                  summary: Not Found
          description: The requested resource was not found
        '503':
          description: API is under maintenance. Check `GET /api/v3/system/status`
            for active periods and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceMaintenance503'
components:
  schemas:
    APIKeyScope:
      type: object
      properties:
        workspace_id:
          type: integer
        workspace_name:
          type: string
        workspace_upload_method:
          type: string
        workspace_datasource_type:
          type:
          - string
          - 'null'
          readOnly: true
        role:
          type: string
        scope_type:
          allOf:
          - $ref: '#/components/schemas/ScopeTypeEnum'
          readOnly: true
      required:
      - role
      - scope_type
      - workspace_datasource_type
      - workspace_id
      - workspace_name
      - workspace_upload_method
    APIKeyScopeRequest:
      type: object
      description: One entry in the `scopes` list — a workspace + a role on it.
      properties:
        workspace_id:
          type: integer
          minimum: 1
        role:
          $ref: '#/components/schemas/RoleEnum'
      required:
      - role
      - workspace_id
    APIKeyV3Response:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        prefix:
          type: string
        created_at:
          type: string
          format: date-time
        expires_at:
          type:
          - string
          - 'null'
          format: date-time
        scopes:
          type: array
          items:
            $ref: '#/components/schemas/APIKeyScope'
          readOnly: true
      required:
      - created_at
      - expires_at
      - id
      - name
      - prefix
      - scopes
    APIV3BatchErrorResponse:
      type: object
      properties:
        id:
          type:
          - string
          - 'null'
          description: Job/resource id when one already exists (useful for async error
            diagnosis); null otherwise.
        code:
          type: integer
          description: HTTP status code
        error:
          type: string
          description: Error code used by the UI as a translation key
        detail:
          type: string
          description: Human-readable error message for developers
        doc_url:
          type: string
          description: Link to the error-code documentation page
        index:
          type: integer
          description: 0-based position of the failing action in the batch.
      required:
      - code
      - detail
      - doc_url
      - error
      - id
    APIV3ErrorResponse:
      type: object
      properties:
        id:
          type:
          - string
          - 'null'
          description: Job/resource id when one already exists (useful for async error
            diagnosis); null otherwise.
        code:
          type: integer
          description: HTTP status code
        error:
          type: string
          description: Error code used by the UI as a translation key
        detail:
          type: string
          description: Human-readable error message for developers
        doc_url:
          type: string
          description: Link to the error-code documentation page
      required:
      - code
      - detail
      - doc_url
      - error
      - id
    APIV3FieldError:
      type: object
      properties:
        error:
          type: string
          description: Error code / translation key
        detail:
          type: string
          description: Human-readable description of the field error
      required:
      - detail
      - error
    APIV3ValidationErrorResponse:
      type: object
      properties:
        id:
          type:
          - string
          - 'null'
          description: Job/resource id when one already exists (useful for async error
            diagnosis); null otherwise.
        code:
          type: integer
          description: HTTP status code
        error:
          type: string
          description: Error code used by the UI as a translation key
        detail:
          type: string
          description: Human-readable error message for developers
        doc_url:
          type: string
          description: Link to the error-code documentation page
        fields:
          type: object
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/APIV3FieldError'
          description: Field-level validation errors keyed by field name
      required:
      - code
      - detail
      - doc_url
      - error
      - id
    AskRequest:
      type: object
      description: |-
        DRF serializer mixin providing ``content_type`` and ``attribute`` fields.

        Compose into any request serializer via multiple inheritance::

            class SearchRequestSerializer(FacetFilterFieldsMixin, serializers.Serializer):
                query = serializers.CharField(...)
                # content_type and attribute inherited from the mixin
      properties:
        content_type:
          type: array
          items:
            type: string
          description: 'Filter by content type path. Multiple values are OR. Exact-or-subtree
            matching by default (e.g. `legal` matches legal, legal:contract). Wildcards:
            `*contract*` (contains), `legal:contract*` (prefix).'
        attribute:
          type: array
          items:
            type: string
          description: 'Filter by attribute value. **Repeated `attribute` entries
            are ANDed; values inside one entry are ORed with `|`** (pipe is the recommended
            OR delimiter — comma also works but can be ambiguous with multi-key values).
            Example: `attribute=fiscal_year:2024|2025&attribute=status:active` → (fiscal_year
            2024 OR 2025) AND (status active). Formats: `name` (has any value), `name:value`
            (exact), `name:>value` / `name:>=value` (gt/gte), `name:<value` / `name:<=value`
            (lt/lte), `name:prefix*` (starts with, case-insensitive), `name:*text*`
            (contains, case-insensitive), `name:a|b` (OR). Smart dates: `filing_date:2023`
            (year), `filing_date:2023-06` (month). Type-aware: booleans (true/false),
            multi-select (membership check). Scoped: `content_type(legal:compliance).regulation:AML`.'
        query:
          type: string
          description: Natural-language question. Maximum 1500 characters.
          maxLength: 1500
        max_results:
          type: integer
          maximum: 50
          minimum: 1
          default: 10
          description: 'Maximum number of chunks to retrieve for context. Range: 1–50.'
        workspace_id:
          type: array
          items:
            type: integer
          description: Restrict search to these workspace IDs. Cannot combine with
            file_id.
        tag_id:
          type: array
          items:
            type: integer
          description: Restrict to documents carrying any of these tag IDs (OR). Cannot
            combine with file_id.
        file_id:
          type: array
          items:
            type: integer
          description: Restrict to specific file IDs. Cannot combine with workspace_id
            or tag_id.
        relevance_scoring:
          allOf:
          - $ref: '#/components/schemas/RelevanceScoringEnum'
          default: scoring_and_filtering
          description: |-
            Controls the relevance scoring step used during retrieval. "none": Skip scoring — lowest latency, relevance score is null in each result. "scoring_only": Score every candidate but return them all. Omit for the default (score and filter).

            * `none` - none
            * `scoring_only` - scoring_only
            * `scoring_and_filtering` - scoring_and_filtering
        stream:
          type: boolean
          default: false
          description: When true, response is streamed as Server-Sent Events.
        model:
          type:
          - string
          - 'null'
          description: |-
            LLM used for answer generation. Omit to use the default model configured for your organization. Standard values:
            - `mistral-large-latest`: Mistral Large 2 — flagship general-purpose model. Best answer quality.
            - `alfred-ft5`: Alfred FT5 — LightOn fine-tuned model, lighter and faster for straightforward questions.
            Custom model technical names (e.g. `custom-{company_id}-{uuid}`) are also accepted.
        response_format:
          description: 'JSON Schema object for structured output. When provided, the
            LLM answer is constrained to match this schema. Must have `type: "object"`
            and `properties`.'
      required:
      - query
    AskResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/AskResultItem'
          description: Retrieved chunks used as context, ordered by relevance score
            descending.
        answer:
          type: string
          description: LLM-generated answer grounded in the retrieved results.
      required:
      - answer
      - results
    AskResultItem:
      type: object
      properties:
        chunk_id:
          type: string
          format: uuid
          description: Chunk UUID.
        content:
          type:
          - string
          - 'null'
          description: Chunk text content. Null for vision-mode chunks.
        score:
          type: number
          format: double
          description: Effective relevance score — the sort key. Equals scores.relevance
            (0–1) when relevance scoring ran, otherwise the combined retrieval score
            (higher is better, no fixed upper bound). Results are ordered by this
            value descending.
        scores:
          allOf:
          - $ref: '#/components/schemas/SearchScores'
          description: Per-signal score breakdown.
        image:
          allOf:
          - $ref: '#/components/schemas/SearchImage'
          description: Page image. Present only when include_image=true.
        source:
          allOf:
          - $ref: '#/components/schemas/SearchSource'
          description: Source document metadata.
        workspace:
          oneOf:
          - $ref: '#/components/schemas/SearchWorkspace'
          - type: 'null'
          description: Workspace the document belongs to.
        bboxes:
          type: array
          items:
            $ref: '#/components/schemas/SearchBbox'
          description: Merged bounding boxes for the chunk's text on the source PDF.
            Present only when include_bboxes=true. Empty list for vision-mode, non-PDF,
            or pre-v2.2.1 chunks.
        warnings:
          type: array
          items:
            $ref: '#/components/schemas/SearchWarning'
          description: Present only when a pipeline signal degrades. Absent in the
            happy path.
      required:
      - chunk_id
      - content
      - score
      - scores
      - source
      - workspace
    AttributeDefResponse:
      properties:
        name:
          title: Name
          type: string
        label:
          title: Label
          type: string
        type:
          title: Type
          type: string
        required:
          title: Required
          type: boolean
        description:
          default: ''
          title: Description
          type: string
        choices:
          default: []
          items:
            type: string
          title: Choices
          type: array
      required:
      - name
      - label
      - type
      - required
      title: AttributeDefResponse
      type: object
    AttributeSchema:
      properties:
        name:
          description: Attribute identifier in snake_case.
          title: Name
          type: string
        label:
          default: ''
          description: Human-readable attribute label.
          title: Label
          type: string
        value:
          anyOf:
          - type: string
          - type: integer
          - type: number
          - type: boolean
          - items:
              type: string
            type: array
          - type: 'null'
          description: 'Current attribute value. Shape depends on type: string, number,
            boolean, date string, or array of strings for multi-select. Null when
            unset.'
          title: Value
        type:
          description: Public attribute type, e.g. text, number, date, boolean, select,
            multi-select.
          title: Type
          type: string
        required:
          description: Whether the attribute is required by the schema.
          title: Required
          type: boolean
        description:
          default: ''
          description: Optional descriptive text from the schema.
          title: Description
          type: string
        choices:
          default: []
          description: Allowed values for select and multi-select attributes.
          items:
            type: string
          title: Choices
          type: array
      required:
      - name
      - value
      - type
      - required
      title: AttributeSchema
      type: object
    AttributeValueResponse:
      properties:
        name:
          title: Name
          type: string
        value:
          anyOf:
          - type: string
          - type: integer
          - type: number
          - type: boolean
          - items:
              type: string
            type: array
          - type: 'null'
          description: 'Attribute value. Shape depends on type: string, number, boolean,
            date string, or array of strings for multi-select.'
          title: Value
        content_type_path:
          title: Content Type Path
          type: string
      required:
      - name
      - value
      - content_type_path
      title: AttributeValueResponse
      type: object
    BatchResponse:
      properties:
        results:
          items:
            $ref: '#/components/schemas/BatchResultItem'
          title: Results
          type: array
      required:
      - results
      title: BatchResponse
      type: object
    BatchResultItem:
      properties:
        status:
          title: Status
          type: integer
        data:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          default: null
          title: Data
      required:
      - status
      title: BatchResultItem
      type: object
    BlankEnum:
      enum:
      - ''
    BrowseFolderItem:
      type: object
      description: A single folder entry returned by the datasource browse endpoint.
      properties:
        id:
          type: string
          description: Provider folder identifier (SharePoint item id or Google Drive
            file id).
        name:
          type: string
          description: Folder display name.
        has_children:
          type: boolean
          description: 'Best-effort hint for the tree UI: True when the folder is
            known or assumed to contain subfolders.'
        path:
          type:
          - string
          - 'null'
          description: Full path from the drive root (SharePoint only). Null for Google
            Drive.
        drive_id:
          type:
          - string
          - 'null'
          description: SharePoint drive containing the folder. Set for items returned
            inside a document library; null for library entries themselves and for
            Google Drive.
        kind:
          allOf:
          - $ref: '#/components/schemas/KindEnum'
          default: folder
          description: |-
            Item kind. SharePoint root returns 'library' entries (document libraries); everything else is 'folder'.

            * `library` - library
            * `folder` - folder
      required:
      - has_children
      - id
      - name
    BudgetAlertResponse:
      properties:
        id:
          title: Id
          type: integer
        is_enabled:
          title: Is Enabled
          type: boolean
        threshold_type:
          title: Threshold Type
          type: string
        threshold_value:
          pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
          title: Threshold Value
          type: string
      required:
      - id
      - is_enabled
      - threshold_type
      - threshold_value
      title: BudgetAlertResponse
      type: object
    BudgetResponse:
      properties:
        is_enabled:
          description: Whether this budget is actively enforced.
          title: Is Enabled
          type: boolean
        amount_eur:
          description: Monthly budget cap in EUR.
          pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
          title: Amount Eur
          type: string
        currency:
          default: EUR
          description: ISO 4217 currency code.
          title: Currency
          type: string
        current_cycle_start:
          description: First day of the current billing cycle (ISO date).
          title: Current Cycle Start
          type: string
        next_cycle_start:
          description: First day of the next billing cycle (ISO date).
          title: Next Cycle Start
          type: string
        monthly_spend_eur:
          description: Current month's spend in EUR.
          pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
          title: Monthly Spend Eur
          type: string
        available_eur:
          description: Remaining budget for the current cycle in EUR.
          pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
          title: Available Eur
          type: string
        alerts:
          description: Alert thresholds.
          items:
            $ref: '#/components/schemas/BudgetAlertResponse'
          title: Alerts
          type: array
      required:
      - is_enabled
      - amount_eur
      - current_cycle_start
      - next_cycle_start
      - monthly_spend_eur
      - available_eur
      title: BudgetResponse
      type: object
    ContentTypeActionRequest:
      description: |-
        Request body for POST /api/v3/content-types.

        Action-dispatched per FAC0012. Every action is idempotent.

        Schema-side verb family:
          - ``adopt`` — bulk import from the Pydantic seed catalog.
          - ``define_content_type`` / ``undefine_content_type`` — CRUD on tree nodes.
          - ``define_attribute`` / ``undefine_attribute`` — CRUD on attribute columns.

        Fields are validated per action in ``validate_fields_for_action`` — top-level
        optionality mirrors the union of action shapes, so consumers only need a
        single Pydantic class (friendly to drf-spectacular), but the validator
        enforces the narrow contract per action, the same pattern used by
        ``FileFacetActionRequest``.
      properties:
        action:
          allOf:
          - $ref: '#/components/schemas/ContentTypeActionRequestActionEnum'
          title: Action
        content_types:
          default: []
          items:
            type: string
          title: Content Types
          type: array
        parent_path:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Parent Path
        code:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Code
        content_type_path:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: Colon-separated content type path.
          title: Content Type Path
        label:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: Human-readable label for the node or attribute.
          title: Label
        description:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: Optional descriptive text for the node or attribute.
          title: Description
        inherit_attributes:
          anyOf:
          - type: boolean
          - type: 'null'
          default: null
          description: Whether child content types inherit attributes from ancestors.
            Defaults to true on create.
          title: Inherit Attributes
        name:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: Attribute identifier in snake_case.
          title: Name
        attribute_type:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: 'Public attribute type. Supported values: text, number, date,
            boolean, select, multi-select, rich-text. Accepted aliases: multi_select,
            multiselect, rich_text, richtext.'
          title: Attribute Type
        required:
          anyOf:
          - type: boolean
          - type: 'null'
          default: null
          description: Whether the attribute is required. Defaults to false.
          title: Required
        choices:
          anyOf:
          - items:
              type: string
            type: array
          - type: 'null'
          default: null
          description: Required for select and multi-select attributes. Must be omitted
            for all other types.
          title: Choices
      required:
      - action
      title: ContentTypeActionRequest
      type: object
    ContentTypeActionRequestActionEnum:
      enum:
      - adopt
      - define_content_type
      - undefine_content_type
      - define_attribute
      - undefine_attribute
      type: string
    ContentTypeAssignmentResponse:
      properties:
        content_type_path:
          title: Content Type Path
          type: string
        label:
          title: Label
          type: string
      required:
      - content_type_path
      - label
      title: ContentTypeAssignmentResponse
      type: object
    ContentTypeAttributesResponse:
      properties:
        path:
          description: Canonical colon-separated content type path.
          title: Path
          type: string
        code:
          description: Leaf node code (last segment of the path).
          title: Code
          type: string
        label:
          description: Leaf label for the content type path.
          title: Label
          type: string
        labels:
          default: []
          items:
            type: string
          title: Labels
          type: array
        attributes:
          items:
            $ref: '#/components/schemas/AttributeSchema'
          title: Attributes
          type: array
      required:
      - path
      - code
      - label
      - attributes
      title: ContentTypeAttributesResponse
      type: object
    ContentTypeBatchRequest:
      description: |-
        Batch request for content-type schema operations.

        All actions are validated upfront before any execution begins.
      properties:
        actions:
          items:
            $ref: '#/components/schemas/ContentTypeActionRequest'
          maxItems: 50
          minItems: 1
          title: Actions
          type: array
      required:
      - actions
      title: ContentTypeBatchRequest
      type: object
    ContentTypeNodeResponse:
      properties:
        path:
          title: Path
          type: string
        code:
          title: Code
          type: string
        label:
          title: Label
          type: string
        description:
          default: ''
          title: Description
          type: string
        source:
          title: Source
          type: string
        inherit_attributes:
          default: true
          title: Inherit Attributes
          type: boolean
        attributes:
          default: []
          items:
            $ref: '#/components/schemas/AttributeDefResponse'
          title: Attributes
          type: array
        children:
          default: []
          items:
            $ref: '#/components/schemas/ContentTypeNodeResponse'
          title: Children
          type: array
      required:
      - path
      - code
      - label
      - source
      title: ContentTypeNodeResponse
      type: object
    ContentTypeWrite200Response:
      oneOf:
      - $ref: '#/components/schemas/ContentTypesListResponse'
      - $ref: '#/components/schemas/ContentTypeNodeResponse'
      - $ref: '#/components/schemas/AttributeDefResponse'
    ContentTypeWrite201Response:
      oneOf:
      - $ref: '#/components/schemas/ContentTypeNodeResponse'
      - $ref: '#/components/schemas/AttributeDefResponse'
    ContentTypesListResponse:
      properties:
        content_types:
          items:
            $ref: '#/components/schemas/ContentTypeNodeResponse'
          title: Content Types
          type: array
        can_edit:
          anyOf:
          - type: boolean
          - type: 'null'
          default: null
          title: Can Edit
      required:
      - content_types
      title: ContentTypesListResponse
      type: object
    CreateAPIKeyV3Request:
      type: object
      description: Reject any request fields not declared on the serializer.
      properties:
        name:
          type: string
          maxLength: 250
        expires_at:
          type:
          - string
          - 'null'
          format: date-time
          description: Expiration datetime for the API key. Set to a future datetime
            to expire the key at that time, or null to create a key that never expires.
        scopes:
          type: array
          items:
            $ref: '#/components/schemas/APIKeyScopeRequest'
          description: 'Optional list of `{workspace_id, role}` entries. Providing
            this field marks the key as workspace-scoped: it can only access the listed
            workspaces, with the per-workspace role shown. The requested role on each
            workspace is capped at the role you currently hold there.'
      required:
      - expires_at
      - name
    CreateAPIKeyV3Response:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        prefix:
          type: string
        created_at:
          type: string
          format: date-time
        expires_at:
          type:
          - string
          - 'null'
          format: date-time
        scopes:
          type: array
          items:
            $ref: '#/components/schemas/APIKeyScope'
          readOnly: true
        key:
          type: string
      required:
      - created_at
      - expires_at
      - id
      - key
      - name
      - prefix
      - scopes
    CreatedBy:
      type: object
      description: Shallow user object for the file creator.
      properties:
        id:
          type: integer
          description: User ID
        first_name:
          type: string
          description: First name
        last_name:
          type: string
          description: Last name
        username:
          type: string
          description: Username
      required:
      - first_name
      - id
      - last_name
      - username
    DocumentAttributesListResponse:
      properties:
        content_types:
          items:
            $ref: '#/components/schemas/ContentTypeAttributesResponse'
          title: Content Types
          type: array
        can_edit:
          title: Can Edit
          type: boolean
        unlinked:
          default: []
          items:
            $ref: '#/components/schemas/AttributeSchema'
          title: Unlinked
          type: array
      required:
      - content_types
      - can_edit
      title: DocumentAttributesListResponse
      type: object
    DocumentFacetAttributeValueSchema:
      type: object
      description: OpenAPI schema for a compact attribute value entry.
      properties:
        value:
          description: Attribute value (type depends on attribute definition)
        type:
          type: string
          description: Attribute type (text, number, date, boolean, select, multi_select)
        label:
          type: string
          description: User-readable attribute label (present when include_details=true)
      required:
      - type
      - value
    DocumentFacetCompactSchema:
      type: object
      description: OpenAPI schema for compact content type response (Tier 1 — list
        default).
      properties:
        path:
          type: string
          description: Colon-separated content type path (e.g. legal:contract:nda)
        label:
          type: string
          description: User-readable label (leaf node)
        attribute_values:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DocumentFacetAttributeValueSchema'
          description: Map of attribute name to {value, type}. Only present when include_details=true.
      required:
      - label
      - path
    DocumentSummaryResponse:
      type: object
      properties:
        language:
          allOf:
          - $ref: '#/components/schemas/LanguageEnum'
          description: |-
            Language of the summary.

            * `en` - English
            * `fr` - French
            * `es` - Spanish
            * `it` - Italian
            * `ar` - Arabic
            * `nl` - Dutch
            * `sv` - Swedish
            * `de` - German
            * `ja` - Japanese
            * `zh` - Chinese
            * `ko` - Korean
        summary:
          type: string
          description: Summary of the document.
      required:
      - summary
    ExternalMetadataRequest:
      type: object
      description: |-
        Validates external document metadata for V3 file endpoints.

        All fields are optional to support both creation (where doc_id is typically
        required - validated at the view level) and partial updates (all optional).
      properties:
        external_id:
          type: string
          description: External document ID in the source system. Required when creating
            external metadata for the first time.
        doc_type:
          type: string
          description: External document type (e.g. 'incident', 'page')
        additional_metadata:
          description: Arbitrary JSON object with extra information about the document
            (e.g. URL, version, timestamps). Passed through as-is.
    ExternalMetadataResponse:
      type: object
      properties:
        external_id:
          type: string
          description: External document ID
        doc_type:
          type: string
          description: External document type
        additional_metadata:
          description: Additional metadata associated with the document
      required:
      - additional_metadata
      - doc_type
      - external_id
    ExtractDocument:
      properties:
        filename:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Filename
        page_count:
          anyOf:
          - type: integer
          - type: 'null'
          default: null
          title: Page Count
        file_size_bytes:
          anyOf:
          - type: integer
          - type: 'null'
          default: null
          title: File Size Bytes
        mime_type:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Mime Type
      title: ExtractDocument
      type: object
    ExtractJobResponse:
      properties:
        id:
          title: Id
          type: string
        status:
          title: Status
          type: string
        created_at:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default: null
          title: Created At
        completed_at:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default: null
          title: Completed At
        processing_time_ms:
          anyOf:
          - type: integer
          - type: 'null'
          default: null
          title: Processing Time Ms
        document:
          anyOf:
          - $ref: '#/components/schemas/ExtractDocument'
          - type: 'null'
          default: null
        result:
          anyOf:
          - $ref: '#/components/schemas/ExtractResult'
          - type: 'null'
          default: null
        usage:
          anyOf:
          - $ref: '#/components/schemas/ExtractUsage'
          - type: 'null'
          default: null
        progress:
          anyOf:
          - $ref: '#/components/schemas/JobProgress'
          - type: 'null'
          default: null
      required:
      - id
      - status
      title: ExtractJobResponse
      type: object
    ExtractPagination:
      properties:
        page:
          title: Page
          type: integer
        page_size:
          title: Page Size
          type: integer
        total_items:
          title: Total Items
          type: integer
        total_pages:
          title: Total Pages
          type: integer
        has_next:
          title: Has Next
          type: boolean
        has_prev:
          title: Has Prev
          type: boolean
      required:
      - page
      - page_size
      - total_items
      - total_pages
      - has_next
      - has_prev
      title: ExtractPagination
      type: object
    ExtractRequest:
      description: |-
        Body for POST /api/v3/extract.

        ``schema`` is the JSON Schema that drives extraction. It arrives as a dict
        on JSON requests and as a JSON-encoded string on multipart requests — both
        are coerced to ``dict``.

        ``options`` is a free-form dict; currently supports ``{"async": bool}``.
      properties:
        document:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Document
        file_id:
          anyOf:
          - type: integer
          - type: 'null'
          default: null
          title: File Id
        schema:
          additionalProperties: true
          title: Schema
          type: object
        options:
          additionalProperties: true
          title: Options
          type: object
      required:
      - schema
      title: ExtractRequest
      type: object
    ExtractResult:
      properties:
        data:
          anyOf:
          - items:
              additionalProperties: true
              type: object
            type: array
          - type: 'null'
          default: null
          title: Data
        pagination:
          anyOf:
          - $ref: '#/components/schemas/ExtractPagination'
          - type: 'null'
          default: null
      title: ExtractResult
      type: object
    ExtractUsage:
      properties:
        pages_processed:
          anyOf:
          - type: integer
          - type: 'null'
          default: null
          title: Pages Processed
      title: ExtractUsage
      type: object
    FacetScopeRequest:
      description: Request body for POST /api/v3/content-types/scope.
      properties:
        query:
          anyOf:
          - maxLength: 2000
            type: string
          - type: 'null'
          default: null
          description: Search query. Omit to get the full schema context for system
            prompts.
          title: Query
        max_results:
          default: 20
          description: Max content types to return.
          maximum: 100
          minimum: 1
          title: Max Results
          type: integer
        threshold:
          default: 1.8
          description: '[Beta] Score threshold for has_signal. Set to 0 to disable.'
          minimum: 0
          title: Threshold
          type: number
        model:
          anyOf:
          - maxLength: 256
            type: string
          - type: 'null'
          default: null
          description: Model technical name for LLM completion. When provided, the
            API calls the model with the prompt_context and returns a scope_completion
            with the parsed and normalized result. Omit to return prompt_context only.
          title: Model
        relevance_scoring:
          anyOf:
          - const: none
            type: string
          - type: 'null'
          default: null
          description: 'Controls the relevance scoring step. Omit (default) to retrieve
            and score content types by query relevance. "none": Skip retrieval scoring
            and return all content types (score=0). Useful with model for LLM completion
            over the full catalog. When ''none'', max_results and threshold are ignored.'
          title: Relevance Scoring
      title: FacetScopeRequest
      type: object
    FacetScopeResponse:
      properties:
        has_signal:
          title: Has Signal
          type: boolean
        groups:
          items:
            $ref: '#/components/schemas/RootGroup'
          title: Groups
          type: array
        prompt_context:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Prompt Context
        prompt_version:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Prompt Version
        scope_completion:
          anyOf:
          - $ref: '#/components/schemas/ScopeCompletion'
          - type: 'null'
          default: null
      required:
      - has_signal
      - groups
      title: FacetScopeResponse
      type: object
    FileBulkDeleteRequestSerializerV3:
      type: object
      description: Request serializer for V3 bulk file deletion.
      properties:
        ids:
          type: array
          items:
            type: integer
            minimum: 1
      required:
      - ids
    FileCreateRequestSerializerV3:
      type: object
      description: |-
        Request serializer for POST /api/v3/files endpoint.

        Phase 1 Implementation - Core Parameters:
        - file: The file to upload (required)
        - name: Custom filename (optional, defaults to uploaded filename)
        - title: Custom title for the document (optional)
        - workspace_id: Workspace ID where the document will be stored (required)
        - parser: Deprecated — ignored, the platform always uses its default pipeline
      properties:
        file:
          type: string
          format: uri
          description: The file to upload (binary data)
        filename:
          type: string
          description: Custom filename (defaults to uploaded filename if not provided)
          maxLength: 255
        title:
          type: string
          description: Custom title for the document. If not provided, defaults to
            filename without extension.
          maxLength: 255
        workspace_id:
          type: integer
          description: Workspace where the document will be stored.
        parser:
          type: string
          deprecated: true
          description: Deprecated — the platform always uses its default ingestion
            pipeline. This field is accepted but ignored. Will be removed in a future
            release.
          maxLength: 255
        tags:
          type: array
          items:
            type: integer
          description: List of tag IDs to assign to the document on creation.
        external_metadata:
          oneOf:
          - $ref: '#/components/schemas/ExternalMetadataRequest'
          - type: 'null'
          description: External source metadata for documents ingested from third-party
            systems. Provide as a JSON object with `external_id` (required), `doc_type`
            (optional), and `additional_metadata` (optional JSON object).
      required:
      - file
      - workspace_id
    FileCreateResponseSerializerV3:
      type: object
      properties:
        id:
          type: integer
          readOnly: true
        filename:
          type: string
          readOnly: true
          description: Filename of the document
        workspace:
          oneOf:
          - $ref: '#/components/schemas/WorkspaceInFileResponseSerializerV3'
          - type: 'null'
          readOnly: true
          description: Workspace the document belongs to
        summaries:
          type: array
          items:
            $ref: '#/components/schemas/DocumentSummaryResponse'
          readOnly: true
          description: Document summaries (all languages)
        title:
          type:
          - string
          - 'null'
          maxLength: 255
        extension:
          type: string
          description: File extension of the document
        status:
          $ref: '#/components/schemas/StatusEnum'
        status_vision:
          $ref: '#/components/schemas/StatusVisionEnum'
        created_at:
          type: string
          format: date-time
          description: Creation date of the resource
        updated_at:
          type: string
          format: date-time
          readOnly: true
        total_pages:
          type: integer
          readOnly: true
          description: Total number of pages
        tags:
          type: array
          items:
            $ref: '#/components/schemas/TagItem'
          readOnly: true
          description: List of tags associated with the document
        created_by:
          oneOf:
          - $ref: '#/components/schemas/CreatedBy'
          - type: 'null'
          readOnly: true
          description: User who created the file. Null when the file was created by
            the system.
        upload_session_uuid:
          type:
          - string
          - 'null'
          format: uuid
          readOnly: true
          description: Upload session UUID associated with this document
        external_metadata:
          oneOf:
          - $ref: '#/components/schemas/ExternalMetadataResponse'
          - type: 'null'
          description: External document metadata
        message:
          type: string
          readOnly: true
          description: Status message about the file upload
      required:
      - created_at
      - created_by
      - extension
      - external_metadata
      - filename
      - id
      - message
      - summaries
      - tags
      - total_pages
      - updated_at
      - upload_session_uuid
      - workspace
    FileFacetActionRequest:
      description: |-
        Write operation for a file's facets (classifications + attribute values).

        Explicit verb-noun actions per FAC0012:
          - ``classify`` / ``unclassify``: T2 (file ↔ content type)
          - ``set_value`` / ``clear_value``: T3 (attribute value under an assigned content type)

        Value actions require ``attribute_name``; classification actions require only
        ``content_type_path``.
      properties:
        action:
          allOf:
          - $ref: '#/components/schemas/FileFacetActionRequestActionEnum'
          title: Action
        content_type_path:
          description: Assigned content type path, e.g. legal:contract:nda.
          title: Content Type Path
          type: string
        attribute_name:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          description: Attribute identifier in snake_case.
          title: Attribute Name
        value:
          default: null
          description: 'Attribute value for set_value. Shape depends on attribute
            type: text/rich-text=string, number=number, date=date string (YYYY-MM-DD),
            boolean=true/false, select=string from choices, multi-select=array of
            strings from choices.'
          title: Value
      required:
      - action
      - content_type_path
      title: FileFacetActionRequest
      type: object
    FileFacetActionRequestActionEnum:
      enum:
      - classify
      - unclassify
      - set_value
      - clear_value
      type: string
    FileFacetBatchRequest:
      description: |-
        Batch request for file facet operations.

        All actions are validated upfront before any execution begins.
      properties:
        actions:
          items:
            $ref: '#/components/schemas/FileFacetActionRequest'
          maxItems: 50
          minItems: 1
          title: Actions
          type: array
      required:
      - actions
      title: FileFacetBatchRequest
      type: object
    FileFacetWriteResponse:
      oneOf:
      - $ref: '#/components/schemas/AttributeValueResponse'
      - $ref: '#/components/schemas/ContentTypeAssignmentResponse'
    FileListResponseSerializerV3:
      type: object
      properties:
        id:
          type: integer
          readOnly: true
        filename:
          type: string
          readOnly: true
          description: Filename of the document
        workspace:
          oneOf:
          - $ref: '#/components/schemas/WorkspaceInFileResponseSerializerV3'
          - type: 'null'
          readOnly: true
          description: Workspace the document belongs to
        summaries:
          type: array
          items:
            $ref: '#/components/schemas/DocumentSummaryResponse'
          readOnly: true
          description: Document summaries (all languages)
        title:
          type:
          - string
          - 'null'
          maxLength: 255
        extension:
          type: string
          description: File extension of the document
        status:
          $ref: '#/components/schemas/StatusEnum'
        status_detail:
          type:
          - string
          - 'null'
          description: Detailed error information. Only present when document processing
            has failed.
        status_vision:
          $ref: '#/components/schemas/StatusVisionEnum'
        created_at:
          type: string
          format: date-time
          description: Creation date of the resource
        updated_at:
          type: string
          format: date-time
          readOnly: true
        total_pages:
          type: integer
          readOnly: true
          description: Total number of pages
        size:
          type:
          - integer
          - 'null'
          readOnly: true
          description: Size of the file in bytes.
        tags:
          type: array
          items:
            $ref: '#/components/schemas/TagItem'
          readOnly: true
          description: List of tags associated with the document
        created_by:
          oneOf:
          - $ref: '#/components/schemas/CreatedBy'
          - type: 'null'
          readOnly: true
          description: User who created the file. Null when the file was created by
            the system.
        upload_session_uuid:
          type:
          - string
          - 'null'
          format: uuid
          readOnly: true
          description: Upload session UUID associated with this document
        search_details:
          oneOf:
          - $ref: '#/components/schemas/SearchDetails'
          - type: 'null'
          readOnly: true
          description: Only present when search_details=true and search is provided.
        signature:
          type:
          - string
          - 'null'
          readOnly: true
          description: TLSH hash for duplicate detection. Only included when include_details=true
            (detail field).
        parser:
          type:
          - string
          - 'null'
          description: Parser/ingestion pipeline used for document processing (e.g.,
            'v2.1', 'v3.0'). Only included when include_details=true (detail field).
        external_metadata:
          oneOf:
          - $ref: '#/components/schemas/ExternalMetadataResponse'
          - type: 'null'
          description: External document metadata
        content_types:
          type: array
          items:
            $ref: '#/components/schemas/DocumentFacetCompactSchema'
          readOnly: true
          description: Facet content types with nested attribute values. Excludable
            via ?exclude=content_types.
      required:
      - content_types
      - created_at
      - created_by
      - extension
      - filename
      - id
      - tags
      - total_pages
      - updated_at
      - upload_session_uuid
      - workspace
    FileRetrieveResponseSerializerV3:
      type: object
      properties:
        id:
          type: integer
          readOnly: true
        filename:
          type: string
          readOnly: true
          description: Filename of the document
        workspace:
          oneOf:
          - $ref: '#/components/schemas/WorkspaceInFileResponseSerializerV3'
          - type: 'null'
          readOnly: true
          description: Workspace the document belongs to
        summaries:
          type: array
          items:
            $ref: '#/components/schemas/DocumentSummaryResponse'
          readOnly: true
          description: Document summaries (all languages)
        title:
          type:
          - string
          - 'null'
          maxLength: 255
        extension:
          type: string
          description: File extension of the document
        status:
          $ref: '#/components/schemas/StatusEnum'
        status_vision:
          $ref: '#/components/schemas/StatusVisionEnum'
        created_at:
          type: string
          format: date-time
          description: Creation date of the resource
        updated_at:
          type: string
          format: date-time
          readOnly: true
        total_pages:
          type: integer
          readOnly: true
          description: Total number of pages
        size:
          type:
          - integer
          - 'null'
          readOnly: true
          description: Size of the file in bytes.
        tags:
          type: array
          items:
            $ref: '#/components/schemas/TagItem'
          readOnly: true
          description: List of tags associated with the document
        created_by:
          oneOf:
          - $ref: '#/components/schemas/CreatedBy'
          - type: 'null'
          readOnly: true
          description: User who created the file. Null when the file was created by
            the system.
        upload_session_uuid:
          type:
          - string
          - 'null'
          format: uuid
          readOnly: true
          description: Upload session UUID associated with this document
        signature:
          type:
          - string
          - 'null'
          readOnly: true
          description: TLSH hash for duplicate detection.
        content:
          type:
          - string
          - 'null'
          deprecated: true
          readOnly: true
          description: Deprecated — use `pages[]` instead. Full text content of the
            document, derived from per-page text, as a single flat string. Only included
            when include_content=true query parameter is provided. Will be removed
            in a future release.
        pages:
          type: array
          items:
            $ref: '#/components/schemas/Page'
          readOnly: true
          description: Per-page document text in the canonical `{ index, markdown
            }` shape shared with /parse and /ocr. Only included when include_content=true.
            Intended replacement for the flat `content` string. For documents ingested
            before per-page text was stored, the full `content` is returned as a single
            page (index 1); empty only when there is no content at all.
        status_detail:
          type:
          - string
          - 'null'
          description: Detailed error information. Only present when document processing
            has failed.
        parser:
          type:
          - string
          - 'null'
          description: 'Parser/ingestion pipeline used for document processing (e.g.,
            ''v2.1'', ''v3.0''). '
        external_metadata:
          oneOf:
          - $ref: '#/components/schemas/ExternalMetadataResponse'
          - type: 'null'
          description: External document metadata
        content_types:
          type: array
          items:
            $ref: '#/components/schemas/DocumentFacetCompactSchema'
          readOnly: true
          description: Facet content types with nested attribute values. Excludable
            via ?exclude=content_types.
      required:
      - content_types
      - created_at
      - created_by
      - extension
      - filename
      - id
      - signature
      - summaries
      - tags
      - total_pages
      - updated_at
      - upload_session_uuid
      - workspace
    FileTaggingAddRequest:
      type: object
      description: Request serializer for adding tags to a file.
      properties:
        tags:
          type: array
          items:
            type: integer
          description: List of tag IDs to add to the file
          minItems: 1
      required:
      - tags
    JobProgress:
      description: |-
        Live progress of a long-running async job while it is in flight.

        Shared by the parse (``GET /api/v3/parse/<id>``) and extract
        (``GET /api/v3/extract/<id>``) polling envelopes: ``pages_processed`` is the
        count of pages done so far and ``percentage`` is the completion percentage
        [0, 100] derived from it.
      properties:
        percentage:
          title: Percentage
          type: integer
        pages_processed:
          title: Pages Processed
          type: integer
      required:
      - percentage
      - pages_processed
      title: JobProgress
      type: object
    KindEnum:
      enum:
      - library
      - folder
      type: string
      description: |-
        * `library` - library
        * `folder` - folder
    LanguageEnum:
      enum:
      - en
      - fr
      - es
      - it
      - ar
      - nl
      - sv
      - de
      - ja
      - zh
      - ko
      type: string
      description: |-
        * `en` - English
        * `fr` - French
        * `es` - Spanish
        * `it` - Italian
        * `ar` - Arabic
        * `nl` - Dutch
        * `sv` - Swedish
        * `de` - German
        * `ja` - Japanese
        * `zh` - Chinese
        * `ko` - Korean
    ModeEnum:
      enum:
      - text
      - vision
      type: string
      description: |-
        * `text` - text
        * `vision` - vision
    Page:
      type: object
      description: |-
        Canonical per-page document text object.

        Originates with /parse and is reused by /ocr and /files (the latter imports it
        from here) so a client can switch between live parsing and reading an
        already-ingested file without reshaping page data. Defined once and reused
        everywhere — never redefine this shape per app.

        Extensible: future per-page fields (tables, images, confidence, ...) can be
        added here without breaking callers that only consume ``index`` + ``markdown``.
      properties:
        index:
          type: integer
          description: Page number within the document (1-based).
        markdown:
          type: string
          description: Page text rendered as Markdown.
      required:
      - index
      - markdown
    PaginatedAPIKeyV3ResponseList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/APIKeyV3Response'
    PaginatedFileListResponseSerializerV3List:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/FileListResponseSerializerV3'
    PaginatedStandardWorkspaceV3ListResponseList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/StandardWorkspaceV3ListResponse'
    PaginatedTagListResponseSerializerV3List:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/TagListResponseSerializerV3'
    ParseAsyncResponse:
      type: object
      description: Returned by ``POST /api/v3/parse`` with ``options.async=true``
        — caller polls ``GET /api/v3/parse/<id>``.
      properties:
        id:
          type: string
          description: Parse job id (e.g. `parse_Kg`); poll via GET /api/v3/parse/<id>.
        status:
          type: string
          description: Initial status — typically 'pending'.
        created_at:
          type: string
          format: date-time
          description: When the job was accepted.
      required:
      - created_at
      - id
      - status
    ParseDocument:
      type: object
      properties:
        filename:
          type: string
        page_count:
          type:
          - integer
          - 'null'
        file_size_bytes:
          type: integer
        mime_type:
          type: string
      required:
      - file_size_bytes
      - filename
      - mime_type
      - page_count
    ParseError:
      type: object
      description: Failure details surfaced on terminal-failed async parse jobs.
      properties:
        message:
          type: string
      required:
      - message
    ParseJobStatus:
      type: object
      description: |-
        Returned by ``GET /api/v3/parse/<id>`` — async parse job status + (once terminal) result.

        Same shape as the sync ``ParseResponseSerializer`` but with completion fields
        (``result``, ``usage``, ``completed_at``, ``processing_time_ms``,
        ``document.page_count``) allowed to be null while the job is still in flight,
        plus an ``error`` block populated only on terminal failure.
      properties:
        id:
          type: string
        status:
          type: string
        created_at:
          type: string
          format: date-time
        completed_at:
          type:
          - string
          - 'null'
          format: date-time
        processing_time_ms:
          type:
          - integer
          - 'null'
        document:
          oneOf:
          - $ref: '#/components/schemas/ParseDocument'
          - type: 'null'
        result:
          oneOf:
          - $ref: '#/components/schemas/ParseResult'
          - type: 'null'
        usage:
          oneOf:
          - $ref: '#/components/schemas/ParseUsage'
          - type: 'null'
        progress:
          oneOf:
          - $ref: '#/components/schemas/ParseProgress'
          - type: 'null'
        error:
          oneOf:
          - $ref: '#/components/schemas/ParseError'
          - type: 'null'
      required:
      - completed_at
      - created_at
      - document
      - error
      - id
      - processing_time_ms
      - progress
      - result
      - status
      - usage
    ParseJsonRequest:
      type: object
      properties:
        document:
          type: string
          format: uri
          description: Publicly accessible URL of the document to parse.
        options:
          type: object
          properties:
            async:
              type: boolean
              default: false
              description: Queue the document for asynchronous parsing and return
                202 with a job id.
          additionalProperties: true
          description: 'Parse options. Currently supports `{"async": true}` to queue
            the document.'
      required:
      - document
    ParseMultipartRequest:
      type: object
      properties:
        file:
          type: string
          format: binary
          description: The document to parse.
        options:
          type: object
          properties:
            async:
              type: boolean
              default: false
              description: Queue the document for asynchronous parsing and return
                202 with a job id.
          additionalProperties: true
          description: 'Parse options as a JSON-encoded string. Currently supports
            `{"async": true}` to queue the document.'
      required:
      - file
    ParseProgress:
      type: object
      description: Live progress while a polled async job is in flight.
      properties:
        percentage:
          type: integer
          description: Completion percentage [0, 100].
        pages_processed:
          type: integer
          description: Pages parsed so far.
      required:
      - pages_processed
      - percentage
    ParseResponse:
      type: object
      description: Synchronous ``POST /api/v3/parse`` response — the parse completed
        inline.
      properties:
        id:
          type: string
        status:
          type: string
        created_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time
        processing_time_ms:
          type: integer
        document:
          $ref: '#/components/schemas/ParseDocument'
        result:
          $ref: '#/components/schemas/ParseResult'
        usage:
          $ref: '#/components/schemas/ParseUsage'
      required:
      - completed_at
      - created_at
      - document
      - id
      - processing_time_ms
      - result
      - status
      - usage
    ParseResult:
      type: object
      properties:
        pages:
          type: array
          items:
            $ref: '#/components/schemas/Page'
      required:
      - pages
    ParseUsage:
      type: object
      properties:
        pages_processed:
          type: integer
      required:
      - pages_processed
    PatchedFileUpdateRequestSerializerV3:
      type: object
      description: |-
        Request serializer for PATCH /api/v3/files/{id} endpoint.

        Allows partial updates to mutable document fields:
        - title: Update the document title
        - tags: Replace ALL tags for the document (both manual and auto-assigned)
        - external_metadata: Create or update external source metadata

        Immutable fields (if provided, will return 400):
        - file, filename, workspace_id, parser, etc.
      properties:
        title:
          type: string
          description: Updated title for the document.
          maxLength: 255
        tags:
          type: array
          items:
            type: integer
          description: List of tag IDs to replace ALL existing tags (both manual and
            auto-assigned). To remove all tags when using multipart format, send [0]
            as the sentinel value.
        external_metadata:
          oneOf:
          - $ref: '#/components/schemas/ExternalMetadataRequest'
          - type: 'null'
          description: External source metadata to create or update. `external_id`
            is required when no external metadata record exists yet. Fields in `additional_metadata`
            are merged (not replaced) with existing values.
    PatchedUpdateAPIKeyV3Request:
      type: object
      description: Reject any request fields not declared on the serializer.
      properties:
        name:
          type: string
          maxLength: 250
        scopes:
          type: array
          items:
            $ref: '#/components/schemas/APIKeyScopeRequest'
          description: Replace the key's full scope set. Pass an empty list to unscope
            the key. Each entry's role is re-validated against your current role on
            the workspace.
    PatchedUpdateWorkspaceV3Request:
      type: object
      properties:
        name:
          type: string
          description: 'Workspace name (max 100 characters, cannot be empty). When
            sent together with `deleted_at: null` (restore), the workspace is restored
            under this name — used to resolve a collision when the original name was
            re-taken by a live workspace during the grace period.'
        description:
          type: string
          description: 'Workspace description. Send empty string or null to clear.
            May be sent together with `deleted_at: null` (restore) to set the description
            as part of the restore request; a name collision rejects the whole request
            before the description is applied. `members` and `datasource` are not
            accepted on a restore request — restore first, then PATCH them.'
        members:
          description: 'Members with roles in format {"users": [{"id": <user_id>,
            "role": "owner|editor|viewer"}, ...], "groups": [{"id": <group_id>, "role":
            "owner|editor|viewer"}, ...]}. Role defaults to viewer if not specified.
            REPLACES all existing members.'
        datasource:
          allOf:
          - $ref: '#/components/schemas/_DatasourceConversionRequest'
          description: Datasource configuration to convert this workspace into a read-only
            synced workspace. Workspace OWNER (or a role granting workspace edit/delete)
            only. Cannot be undone.
    RelevanceScoringEnum:
      enum:
      - none
      - scoring_only
      - scoring_and_filtering
      type: string
      description: |-
        * `none` - none
        * `scoring_only` - scoring_only
        * `scoring_and_filtering` - scoring_and_filtering
    RelevantChunkScoredV3:
      type: object
      description: |-
        Relevant chunk with the unified scoring shape, aligned with /api/v3/search.

        Exposes ``score`` + ``scores`` (text/vision/keyword/multivector/relevance) instead of
        the legacy final_score/lexical_score/distance. ``scores.relevance`` is always null on
        this path — no relevance scoring runs on file search.
      properties:
        text:
          type: string
          description: Chunk text content
        chunk_type:
          type: string
          description: Chunk type (e.g. text/table)
        score:
          type: number
          format: double
          readOnly: true
          description: Combined retrieval score (higher is better, no fixed upper
            bound). No relevance scoring runs on file search.
        scores:
          allOf:
          - $ref: '#/components/schemas/_ChunkScoresSchema'
          readOnly: true
      required:
      - score
      - scores
      - text
    RoleEnum:
      enum:
      - viewer
      - editor
      - owner
      type: string
      description: |-
        * `viewer` - viewer
        * `editor` - editor
        * `owner` - owner
    RootContentTypeEntry:
      type: object
      properties:
        path:
          type: string
        label:
          type: string
        count:
          type: integer
      required:
      - count
      - label
      - path
    RootGroup:
      properties:
        root:
          title: Root
          type: string
        root_label:
          title: Root Label
          type: string
        max_score:
          title: Max Score
          type: number
        content_types:
          items:
            $ref: '#/components/schemas/ScoredContentType'
          title: Content Types
          type: array
      required:
      - root
      - root_label
      - max_score
      - content_types
      title: RootGroup
      type: object
    ScopeCompletion:
      description: Parsed and normalized LLM scope inference result.
      properties:
        content_type:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Content Type
        attribute:
          default: []
          items:
            type: string
          title: Attribute
          type: array
        raw_output:
          default: ''
          title: Raw Output
          type: string
        normalized:
          default: false
          title: Normalized
          type: boolean
        warnings:
          default: []
          items:
            type: string
          title: Warnings
          type: array
      title: ScopeCompletion
      type: object
    ScopeTypeEnum:
      enum:
      - workspace
      - global
      type: string
      description: |-
        * `workspace` - workspace
        * `global` - global
    ScoredContentType:
      properties:
        path:
          title: Path
          type: string
        label:
          title: Label
          type: string
        root:
          title: Root
          type: string
        score:
          title: Score
          type: number
        chunk_count:
          title: Chunk Count
          type: integer
        doc_count:
          title: Doc Count
          type: integer
        attributes:
          anyOf:
          - items:
              additionalProperties: true
              type: object
            type: array
          - type: 'null'
          default: null
          title: Attributes
      required:
      - path
      - label
      - root
      - score
      - chunk_count
      - doc_count
      title: ScoredContentType
      type: object
    SearchBbox:
      type: object
      properties:
        page_number:
          type: integer
          description: 1-indexed page the rectangle sits on.
        x:
          type: number
          format: double
          description: Left edge in PDF points, top-left origin.
        y:
          type: number
          format: double
          description: Top edge in PDF points, top-left origin (y extends downward).
        width:
          type: number
          format: double
          description: Width in PDF points.
        height:
          type: number
          format: double
          description: Height in PDF points.
        unit:
          type: string
          description: Coordinate unit. Always "pdf_point" in v1.
        origin:
          type: string
          description: Coordinate origin. Always "top_left" in v1.
      required:
      - height
      - origin
      - page_number
      - unit
      - width
      - x
      - y
    SearchDetails:
      type: object
      description: Serializer for search details in file list response.
      properties:
        relevant_chunks:
          type: array
          items:
            $ref: '#/components/schemas/RelevantChunkScoredV3'
          description: Relevant chunks ordered by score descending
      required:
      - relevant_chunks
    SearchExternalMetadata:
      type: object
      properties:
        external_id:
          type: string
          description: ID of the document in the external system.
        external_url:
          type:
          - string
          - 'null'
          description: Deep-link back to the document in the source system. Null if
            not provided.
        additional_metadata:
          type: object
          additionalProperties: {}
          description: Freeform connector metadata. external_url is lifted to its
            own field and excluded here.
      required:
      - additional_metadata
      - external_id
      - external_url
    SearchImage:
      type: object
      properties:
        b64_content:
          type: string
          description: Base64-encoded page image. Empty string when no vision index
            exists for the page.
      required:
      - b64_content
    SearchRequest:
      type: object
      description: |-
        DRF serializer mixin providing ``content_type`` and ``attribute`` fields.

        Compose into any request serializer via multiple inheritance::

            class SearchRequestSerializer(FacetFilterFieldsMixin, serializers.Serializer):
                query = serializers.CharField(...)
                # content_type and attribute inherited from the mixin
      properties:
        content_type:
          type: array
          items:
            type: string
          description: 'Filter by content type path. Multiple values are OR. Exact-or-subtree
            matching by default (e.g. `legal` matches legal, legal:contract). Wildcards:
            `*contract*` (contains), `legal:contract*` (prefix).'
        attribute:
          type: array
          items:
            type: string
          description: 'Filter by attribute value. **Repeated `attribute` entries
            are ANDed; values inside one entry are ORed with `|`** (pipe is the recommended
            OR delimiter — comma also works but can be ambiguous with multi-key values).
            Example: `attribute=fiscal_year:2024|2025&attribute=status:active` → (fiscal_year
            2024 OR 2025) AND (status active). Formats: `name` (has any value), `name:value`
            (exact), `name:>value` / `name:>=value` (gt/gte), `name:<value` / `name:<=value`
            (lt/lte), `name:prefix*` (starts with, case-insensitive), `name:*text*`
            (contains, case-insensitive), `name:a|b` (OR). Smart dates: `filing_date:2023`
            (year), `filing_date:2023-06` (month). Type-aware: booleans (true/false),
            multi-select (membership check). Scoped: `content_type(legal:compliance).regulation:AML`.'
        query:
          type: string
          description: Natural-language search query. Maximum 4000 characters.
          maxLength: 4000
        max_results:
          type: integer
          maximum: 100
          minimum: 1
          default: 10
          description: 'Maximum number of chunks to return after reranking. Range:
            1–100.'
        workspace_id:
          type: array
          items:
            type: integer
          description: Restrict search to these workspace IDs. Cannot combine with
            file_id.
        tag_id:
          type: array
          items:
            type: integer
          description: Restrict to documents carrying any of these tag IDs (OR). Cannot
            combine with file_id.
        file_id:
          type: array
          items:
            type: integer
          description: Restrict to specific file IDs. Cannot combine with workspace_id
            or tag_id.
        mode:
          allOf:
          - $ref: '#/components/schemas/ModeEnum'
          default: text
          description: |-
            "text": hybrid keyword + vector search. "vision": VLM-embedded page image search.

            * `text` - text
            * `vision` - vision
        relevance_scoring:
          allOf:
          - $ref: '#/components/schemas/RelevanceScoringEnum'
          default: scoring_and_filtering
          description: |-
            Controls the relevance scoring step. "scoring_and_filtering" (default): Score candidates for relevance and only return those above the quality threshold. When no candidate clears the threshold, the few best-scoring candidates are returned instead of an empty result; their scores.relevance is then below the usual threshold. "scoring_only": Score every candidate for relevance but return them all, even low-scoring ones. Useful for building your own filtering logic. "none": Skip the relevance scoring step and return all candidates unfiltered. Fastest option, useful when you handle scoring yourself. Omit the field for the default; send "none" to skip. Overrides skip_rerank when both are sent.

            * `none` - none
            * `scoring_only` - scoring_only
            * `scoring_and_filtering` - scoring_and_filtering
        skip_rerank:
          type: boolean
          description: Deprecated — use relevance_scoring. true → relevance_scoring=none,
            false → relevance_scoring=scoring_and_filtering. Ignored when relevance_scoring
            is provided.
        include_image:
          type: boolean
          default: false
          description: Append a base64-encoded page image to each result.
        include_bboxes:
          type: boolean
          default: false
          description: Append merged bounding boxes (in PDF points, top-left origin)
            to each result so callers can overlay chunk highlights on PDF pages. PDF
            documents in text mode only — non-PDF and vision-mode results always return
            an empty list. Omitted from the response entirely when false.
      required:
      - query
    SearchResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/SearchResultItem'
          description: Retrieved chunks, ordered by score descending.
        warnings:
          type: array
          items:
            $ref: '#/components/schemas/SearchWarning'
          description: Present only when a pipeline signal degrades. Absent in the
            happy path.
        explain:
          type: object
          additionalProperties: {}
          description: Scoring breakdown. Present only when explain=true and SEARCH_EXPLAIN_MODE
            is enabled.
      required:
      - results
    SearchResultItem:
      type: object
      properties:
        chunk_id:
          type: string
          format: uuid
          description: Chunk UUID.
        content:
          type:
          - string
          - 'null'
          description: Chunk text content. Null for vision-mode chunks.
        score:
          type: number
          format: double
          description: Effective relevance score — the sort key. Equals scores.relevance
            (0–1) when relevance scoring ran, otherwise the combined retrieval score
            (higher is better, no fixed upper bound). Results are ordered by this
            value descending.
        scores:
          allOf:
          - $ref: '#/components/schemas/SearchScores'
          description: Per-signal score breakdown.
        image:
          allOf:
          - $ref: '#/components/schemas/SearchImage'
          description: Page image. Present only when include_image=true.
        source:
          allOf:
          - $ref: '#/components/schemas/SearchSource'
          description: Source document metadata.
        workspace:
          oneOf:
          - $ref: '#/components/schemas/SearchWorkspace'
          - type: 'null'
          description: Workspace the document belongs to.
        bboxes:
          type: array
          items:
            $ref: '#/components/schemas/SearchBbox'
          description: Merged bounding boxes for the chunk's text on the source PDF.
            Present only when include_bboxes=true. Empty list for vision-mode, non-PDF,
            or pre-v2.2.1 chunks.
      required:
      - chunk_id
      - content
      - score
      - scores
      - source
      - workspace
    SearchScores:
      type: object
      properties:
        text:
          type:
          - number
          - 'null'
          format: double
          description: Semantic text similarity (0–1, higher is better). Null in vision
            mode.
        vision:
          type:
          - number
          - 'null'
          format: double
          description: Vision page similarity (0–1, higher is better). Null when the
            document has no vision index.
        keyword:
          type:
          - number
          - 'null'
          format: double
          description: Keyword match score (higher is better, no fixed upper bound).
            Null in vision mode.
        multivector:
          type:
          - number
          - 'null'
          format: double
          description: Token-level similarity score (higher is better, no fixed upper
            bound). Null when multi-vector scoring is disabled.
        relevance:
          type:
          - number
          - 'null'
          format: double
          description: Relevance score (0–1, higher is better). Populated when relevance_scoring
            is "scoring_only" or "scoring_and_filtering". Null when relevance_scoring
            is "none" or when the scoring model is unavailable.
      required:
      - keyword
      - multivector
      - relevance
      - text
      - vision
    SearchSource:
      type: object
      properties:
        file_id:
          type: integer
          description: File ID.
        filename:
          type: string
          description: Original filename.
        title:
          type:
          - string
          - 'null'
          description: Document title.
        mime_type:
          type:
          - string
          - 'null'
          description: File type (e.g. pdf, docx).
        size_bytes:
          type:
          - integer
          - 'null'
          description: File size in bytes.
        page_start:
          type:
          - integer
          - 'null'
          description: Start page of the chunk (1-indexed).
        page_end:
          type:
          - integer
          - 'null'
          description: End page of the chunk (1-indexed).
        total_pages:
          type: integer
          description: Total pages in the document.
        tags:
          type: array
          items:
            $ref: '#/components/schemas/SearchTag'
          description: Tags associated with the document.
        content_types:
          type: array
          items:
            type: object
            additionalProperties: {}
          description: Facet content type classifications and attribute values.
        external_metadata:
          oneOf:
          - $ref: '#/components/schemas/SearchExternalMetadata'
          - type: 'null'
          description: Null for directly-uploaded documents; present for connector-imported
            documents.
      required:
      - external_metadata
      - file_id
      - filename
      - mime_type
      - page_end
      - page_start
      - size_bytes
      - tags
      - title
      - total_pages
    SearchTag:
      type: object
      properties:
        id:
          type: integer
          description: Tag ID.
        name:
          type: string
          description: Tag name.
      required:
      - id
      - name
    SearchWarning:
      type: object
      properties:
        code:
          type: string
          description: Signal name from the scores object that degraded (e.g. 'relevance').
        reason:
          type: string
          description: Machine-readable failure reason (model_not_found, timeout,
            service_error, unknown).
      required:
      - code
    SearchWorkspace:
      type: object
      properties:
        id:
          type: integer
          description: Workspace ID.
        name:
          type: string
          description: Workspace name.
      required:
      - id
      - name
    StandardWorkspaceCreateV3Request:
      type: object
      description: V3 Request serializer for creating a workspace in the user's company.
      properties:
        name:
          type: string
          maxLength: 100
        description:
          type: string
          default: ''
      required:
      - name
    StandardWorkspaceDatasourceV3Request:
      description: Pydantic request model for datasource conversion and credential
        testing.
      properties:
        type:
          allOf:
          - $ref: '#/components/schemas/StandardWorkspaceDatasourceV3RequestTypeEnum'
          title: Type
        name:
          title: Name
          type: string
        credentials:
          additionalProperties: true
          default: {}
          title: Credentials
          type: object
        filter_criteria:
          additionalProperties: true
          default: {}
          title: Filter Criteria
          type: object
      required:
      - type
      - name
      title: StandardWorkspaceDatasourceV3Request
      type: object
    StandardWorkspaceDatasourceV3RequestTypeEnum:
      enum:
      - googledrive
      - sharepoint
      - servicenow
      - webscrapper
      type: string
    StandardWorkspaceV3DetailsResponse:
      type: object
      description: V3 Response serializer for company workspace creation and retrieval.
      properties:
        id:
          type: integer
        name:
          type: string
        workspace_type:
          type: string
        document_upload_method:
          type: string
        description:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        files_count:
          type: integer
        user_role:
          readOnly: true
          oneOf:
          - $ref: '#/components/schemas/UserRoleEnum'
          - $ref: '#/components/schemas/BlankEnum'
        used_storage:
          type: number
          format: double
        summaries:
          type: array
          items:
            $ref: '#/components/schemas/WorkspaceSummary'
          readOnly: true
        sync:
          oneOf:
          - $ref: '#/components/schemas/WorkspaceSync'
          - type: 'null'
          readOnly: true
        scoped_api_keys:
          type: array
          items:
            $ref: '#/components/schemas/WorkspaceScopedAPIKey'
          readOnly: true
      required:
      - created_at
      - description
      - document_upload_method
      - files_count
      - id
      - name
      - scoped_api_keys
      - summaries
      - sync
      - updated_at
      - used_storage
      - user_role
      - workspace_type
    StandardWorkspaceV3ListResponse:
      type: object
      description: V3 Response serializer for user-level workspaces endpoint.
      properties:
        id:
          type: integer
        name:
          type: string
        workspace_type:
          type: string
        document_upload_method:
          type: string
        description:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        files_count:
          type: integer
        user_role:
          readOnly: true
          oneOf:
          - $ref: '#/components/schemas/UserRoleEnum'
          - $ref: '#/components/schemas/BlankEnum'
        sync:
          oneOf:
          - $ref: '#/components/schemas/WorkspaceSync'
          - type: 'null'
          readOnly: true
        scoped_api_keys:
          type: array
          items:
            $ref: '#/components/schemas/WorkspaceScopedAPIKey'
          readOnly: true
        taxonomy:
          oneOf:
          - $ref: '#/components/schemas/WorkspaceTaxonomy'
          - type: 'null'
          readOnly: true
      required:
      - created_at
      - description
      - document_upload_method
      - files_count
      - id
      - name
      - scoped_api_keys
      - sync
      - taxonomy
      - updated_at
      - user_role
      - workspace_type
    StatusEnum:
      enum:
      - pending
      - pending_conversion
      - converting
      - parsing
      - parsing_failed
      - embedding
      - embedding_failed
      - embedded
      - parsed
      - fail
      - updating
      type: string
      description: |-
        * `pending` - Pending
        * `pending_conversion` - Pending Conversion
        * `converting` - Converting
        * `parsing` - Parsing
        * `parsing_failed` - Parsing Failed
        * `embedding` - Embedding
        * `embedding_failed` - Embedding Failed
        * `embedded` - Embedded
        * `parsed` - Parsed
        * `fail` - Fail
        * `updating` - Updating
    StatusVisionEnum:
      enum:
      - pending
      - processing
      - embedded
      - fail
      - '-'
      type: string
      description: |-
        * `pending` - Pending
        * `processing` - Processing
        * `embedded` - Embedded
        * `fail` - Fail
        * `-` - Not available
    TagCreateRequestSerializerV3:
      type: object
      description: Serializer for creating a tag.
      properties:
        name:
          type: string
          description: Tag name
        description:
          type: string
        auto_assign:
          type: boolean
          default: true
          description: If True, this tag can be automatically assigned by the system.
            If False, it can only be assigned by a user.
      required:
      - description
      - name
    TagItem:
      type: object
      description: Serializer for tag items in file list response.
      properties:
        id:
          type: integer
          description: Tag ID
        name:
          type: string
          description: Tag name
        auto_assigned:
          type: boolean
          description: True if this tag was automatically assigned by the system,
            False if manually assigned by a user
      required:
      - auto_assigned
      - id
      - name
    TagListResponseSerializerV3:
      type: object
      description: Serializer for listing tags.
      properties:
        id:
          type: integer
          readOnly: true
        name:
          type: string
          description: Tag name
        description:
          type: string
          readOnly: true
          description: Description of the tag (max 500 characters).
        auto_assign:
          type: boolean
          readOnly: true
          description: If True, this tag can be automatically assigned by the system.
            If False, it can only be assigned by a user.
        created_at:
          type: string
          format: date-time
          readOnly: true
          description: Timestamp when the tag was created.
        updated_at:
          type: string
          format: date-time
          readOnly: true
          description: Timestamp when the tag was last updated.
        document_count:
          type: integer
          readOnly: true
          description: Number of visible documents with this tag
      required:
      - auto_assign
      - created_at
      - description
      - document_count
      - id
      - name
      - updated_at
    TemplateChildNode:
      properties:
        code:
          title: Code
          type: string
        label:
          title: Label
          type: string
        description:
          default: ''
          title: Description
          type: string
        path:
          title: Path
          type: string
        inherit_attributes:
          default: true
          title: Inherit Attributes
          type: boolean
        children:
          default: []
          items:
            $ref: '#/components/schemas/TemplateChildNode'
          title: Children
          type: array
      required:
      - code
      - label
      - path
      title: TemplateChildNode
      type: object
    TemplateListResponse:
      properties:
        content_types:
          items:
            $ref: '#/components/schemas/TemplateRootNode'
          title: Content Types
          type: array
        playbooks:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          default: null
          title: Playbooks
      required:
      - content_types
      title: TemplateListResponse
      type: object
    TemplateRootNode:
      properties:
        path:
          title: Path
          type: string
        code:
          title: Code
          type: string
        label:
          title: Label
          type: string
        description:
          default: ''
          title: Description
          type: string
        children:
          default: []
          items:
            $ref: '#/components/schemas/TemplateChildNode'
          title: Children
          type: array
        attributes:
          additionalProperties:
            items:
              $ref: '#/components/schemas/AttributeDefResponse'
            type: array
          default: {}
          title: Attributes
          type: object
      required:
      - path
      - code
      - label
      title: TemplateRootNode
      type: object
    UserRoleEnum:
      enum:
      - owner
      - editor
      - viewer
      type: string
      description: "* `owner` - owner\n* `editor` - editor\n* `viewer` - viewer\n\
        * `` - "
    WorkspaceDatasourceBrowseV3Request:
      description: |-
        Pydantic request model for browsing the remote folder hierarchy of a datasource.

        Only browsable providers (Google Drive, SharePoint) are accepted. Credentials are
        validated against the same models as the credential test endpoint.
      properties:
        type:
          allOf:
          - $ref: '#/components/schemas/WorkspaceDatasourceBrowseV3RequestTypeEnum'
          title: Type
        credentials:
          additionalProperties: true
          default: {}
          title: Credentials
          type: object
        drive_id:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Drive Id
        parent_id:
          anyOf:
          - type: string
          - type: 'null'
          default: null
          title: Parent Id
      required:
      - type
      title: WorkspaceDatasourceBrowseV3Request
      type: object
    WorkspaceDatasourceBrowseV3RequestTypeEnum:
      enum:
      - googledrive
      - sharepoint
      type: string
    WorkspaceDatasourceBrowseV3Response:
      type: object
      description: V3 Response serializer for the datasource folder browse endpoint.
      properties:
        folders:
          type: array
          items:
            $ref: '#/components/schemas/BrowseFolderItem'
      required:
      - folders
    WorkspaceInFileResponseSerializerV3:
      type: object
      description: Minimal workspace info for file responses.
      properties:
        id:
          type: integer
          description: Workspace ID
        name:
          type: string
          description: Workspace name
        workspace_type:
          type: string
          description: Workspace type (shared or personal)
      required:
      - id
      - name
      - workspace_type
    WorkspaceScopedAPIKey:
      type: object
      description: |-
        An API key that can access a single workspace, seen from the workspace side.

        Covers both keys explicitly scoped to the workspace (`scope_type="workspace"`,
        each carrying its per-workspace role) and the requesting user's globally-scoped
        keys (`scope_type="global"`), which implicitly reach every workspace in the
        company with the user's own role here. Reads flat dicts built by
        `WorkspaceScopedAPIKeysMixin`, which lists explicitly-scoped keys first.
      properties:
        id:
          type: string
        name:
          type: string
        prefix:
          type: string
        role:
          type: string
        created_at:
          type: string
          format: date-time
        created_by:
          type: string
        scope_type:
          $ref: '#/components/schemas/ScopeTypeEnum'
      required:
      - created_at
      - created_by
      - id
      - name
      - prefix
      - role
      - scope_type
    WorkspaceSummary:
      type: object
      properties:
        language:
          type: string
        summary:
          type: string
      required:
      - language
      - summary
    WorkspaceSync:
      type: object
      properties:
        datasource_type:
          type: string
        source_name:
          type: string
        last_status:
          type: string
        updated_at:
          type:
          - string
          - 'null'
          format: date-time
        failed_files_count:
          type: integer
        next_import_date:
          type:
          - string
          - 'null'
          format: date-time
        editable:
          type: boolean
        name:
          type: string
        instance_url:
          type:
          - string
          - 'null'
        tenant_id:
          type: string
        site_name:
          type: string
        client_id:
          type: string
        filter_criteria: {}
      required:
      - client_id
      - datasource_type
      - editable
      - failed_files_count
      - filter_criteria
      - instance_url
      - last_status
      - name
      - next_import_date
      - site_name
      - source_name
      - tenant_id
      - updated_at
    WorkspaceTaxonomy:
      type: object
      properties:
        classified_files_rate:
          type: number
          format: double
        root_content_types:
          type: array
          items:
            $ref: '#/components/schemas/RootContentTypeEntry'
      required:
      - classified_files_rate
      - root_content_types
    _ChunkScoresSchema:
      type: object
      description: |-
        Per-signal score breakdown. Schema for OpenAPI; higher is better; null = not computed.

        ``text``/``vision`` are 0–1 similarities; ``keyword`` and ``multivector``
        are unbounded (higher is better). Same shape as /api/v3/search and /retrieve.
        ``relevance`` is always null on the file-search path — no relevance scoring
        runs on this endpoint. Defined locally to avoid a circular import with the
        /retrieve serializer module.
      properties:
        text:
          type:
          - number
          - 'null'
          format: double
          description: Semantic text similarity (0–1, higher is better). Null in vision
            mode.
        vision:
          type:
          - number
          - 'null'
          format: double
          description: Vision page similarity (0–1, higher is better). Null when the
            document has no vision index.
        keyword:
          type:
          - number
          - 'null'
          format: double
          description: Keyword match score (higher is better, no fixed upper bound).
            Null in vision mode.
        multivector:
          type:
          - number
          - 'null'
          format: double
          description: Token-level similarity score (higher is better, no fixed upper
            bound). Null when multi-vector scoring is disabled.
        relevance:
          type:
          - number
          - 'null'
          format: double
          description: Relevance score (0–1, higher is better). Always null on file
            search — no relevance scoring runs on this endpoint.
      required:
      - keyword
      - multivector
      - relevance
      - text
      - vision
    _DatasourceConversionRequest:
      type: object
      description: Nested serializer for documentation of the datasource conversion
        payload.
      properties:
        type:
          allOf:
          - $ref: '#/components/schemas/_DatasourceConversionRequestTypeEnum'
          description: |-
            Datasource provider.

            * `servicenow` - servicenow
            * `googledrive` - googledrive
            * `sharepoint` - sharepoint
            * `webscrapper` - webscrapper
        name:
          type: string
          description: Display name for the datasource.
        credentials:
          type: object
          additionalProperties: {}
          description: 'Provider credentials. googledrive: service_account_file (JSON
            string). sharepoint: client_id, client_secret, tenant_id, site_id (opt),
            site_name (opt), instance_url (opt). servicenow: instance_url, username,
            password. webscrapper: none required.'
        filter_criteria:
          type: object
          additionalProperties: {}
          description: 'Provider filter criteria. googledrive: folder_id (required),
            recursive (opt). sharepoint: folder_path (required), recursive (opt).
            servicenow: doc_type (required, e.g. ''knowledge''). webscrapper: start_url
            (required).'
      required:
      - name
      - type
    _DatasourceConversionRequestTypeEnum:
      enum:
      - servicenow
      - googledrive
      - sharepoint
      - webscrapper
      type: string
      description: |-
        * `servicenow` - servicenow
        * `googledrive` - googledrive
        * `sharepoint` - sharepoint
        * `webscrapper` - webscrapper
    ServiceMaintenance503:
      type: object
      description: Returned by the maintenance middleware when the requested endpoint
        is blocked.
      required:
      - detail
      - error
      - mode
      properties:
        detail:
          type: string
          example: System is under maintenance.
        error:
          type: string
          example: service_maintenance
        mode:
          type: string
          enum:
          - full_shutdown
          - warning_banner
          description: '`full_shutdown` blocks all traffic; `warning_banner` also
            blocks and shows a dismissible toast.'
        reason:
          type: string
          description: Operator-supplied maintenance reason, if any.
        started_at:
          type: string
          format: date-time
        endpoint_category_names:
          type: array
          items:
            type: string
          description: Non-empty only for category-scoped periods. Empty means all
            endpoints are affected.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Bearer authentication header of the form `Bearer <token>`, where
        `<token>` is your auth token.
servers:
- url: https://api.lighton.ai
tags:
- name: Ask
  description: 'Retrieval-augmented generation: search your indexed corpus and generate
    an LLM answer grounded in the retrieved passages. Supports streaming (SSE) and
    synchronous modes.'
- name: Search
  description: Hybrid vector + text retrieval over your indexed corpus. Returns ranked
    passages with provenance (file, page range, workspace). Optional reranking and
    vision mode.
- name: Files
  description: Upload, list, fetch, and delete documents indexed in your workspaces.
- name: Facets
  description: Organise documents with hierarchical content types and custom attributes
    per file. Start from starter templates or build your own classification schema
    from scratch.
- name: Tags
  description: Manage flat, company-wide labels used to scope search and group content
    across workspaces.
- name: Workspaces
  description: Create and manage workspaces — the access-controlled containers your
    documents live in.
- name: Parse
  description: Convert documents into structured Markdown — PDFs, images, Office files,
    and HTML. Synchronous endpoint capped at 20 MB / 15 pages.
- name: Extract
  description: Pull typed fields out of documents using a JSON Schema you provide.
    Sync mode for small documents (≤20 MB / 15 pages); async mode for larger jobs
    (≤100 MB / 1000 pages) with polling on a job ID.
- name: API Keys
  description: Provision and revoke API keys used to authenticate against the Console
    API.
- name: Budget
  description: Manage your organization's monthly spend budget and alert thresholds.
    Set a hard cap that blocks API requests when reached, and configure email notifications
    at custom spend percentages.
