> ## Documentation Index
> Fetch the complete documentation index at: https://vaquill.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a matrix

> Build a grid. Nothing is extracted until you run it.

Rows are documents and columns are questions, so the grid is `documents x
columns` cells and each cell is one billable extraction when the matrix is
run. Every document must already be in this matter and finished ingesting:
a still-ingesting document is refused, because retrieval over it would
answer "not in this document" for every column.

Note the column vocabulary: `free_text`, `single_select`, `date`, `money`,
`yes_no`, `party_name`. There is no `text`, `number` or `boolean`.



## OpenAPI

````yaml https://api.vaquill.ai/workspace/openapi/v1.json post /v1/matters/{matterId}/matrices
openapi: 3.1.0
info:
  title: Vaquill Legal Workspace API
  description: >-
    Organization-scoped API for driving your legal workspace from your own
    backend: matters, documents, drafting, review, compare and matrices.


    **Authentication**: `Authorization: Bearer vq_ws_...`. Credentials are
    issued by an organization owner from the automation console at `/automation`
    and are shown once. The organization is resolved from the credential and can
    never be named in a request, so there is no `organizationId` field anywhere
    in this API and sending one is refused.


    This is NOT the Vaquill Data API. That one holds a `vq_key_` credential and
    serves the public legal corpus; the two share no credential, host or
    endpoint, and sending a `vq_key_` here is refused with an error naming the
    other product.


    ## Long-running work


    Anything that costs real work answers `202` with an **operation**. Poll `GET
    /v1/operations/{operationId}` until `status` is `succeeded`, `failed` or
    `cancelled`, honouring `Retry-After` between polls. There are no webhooks,
    so polling is the only completion signal. The five statuses are `queued`,
    `running`, `succeeded`, `failed`, `cancelled`, and there is no sixth: every
    capability reports through the same envelope.


    Send an `Idempotency-Key` on any launch. A retry with the same key and the
    same body returns the FIRST operation rather than starting a second billable
    job, which is what makes recovering from a timeout free.


    ## Identifiers


    Every public id is `<prefix>_<32 lowercase hex>`, for example
    `mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6`. The prefix names the resource type.
    Ids are opaque: take them from responses rather than building them, and
    never pass a bare database uuid.


    ## Lists


    Every collection answers `{data, pagination}`, never a bare array. Page with
    `limit` and `offset`, and read `pagination.total` to size a job before
    running it. `pagination.hasMore` is the reliable signal that rows remain.


    ## Errors


    Errors are RFC 9457 problem documents (`application/problem+json`),
    including for a wrong path and a wrong method. Branch on `type`; it is the
    stable identifier and it resolves to a page describing the failure. `title`
    and `detail` are written for people and may be reworded at any time. Every
    response carries `X-Request-ID`, and every error repeats it as `requestId`:
    quote it when contacting support.


    A `404` is returned identically for a resource that does not exist, one
    belonging to another organization, and one outside your installation's
    matter allowlist. That is deliberate, so the status code cannot be used to
    discover which ids exist elsewhere.


    ## Rate limits


    Limits are per credential and are set by what an operation COSTS rather than
    by its HTTP method, so a `GET` that runs a retrieval is not a read. Each
    operation's tier is fixed; a `429` carries `Retry-After`.


    | Tier | Per minute | Per hour | Per day |

    |---|---|---|---|

    | `poll` | 120 | 3000 | 30000 |

    | `read` | 60 | 1200 | 15000 |

    | `write` | 30 | 600 | 5000 |

    | `launch` | 10 | 200 | 2000 |

    | `download` | 20 | 300 | 3000 |

    | `upload` | 5 | 100 | 500 |


    ## Scopes


    A credential carries an explicit scope set, chosen when it is issued. A call
    outside them is `403` with `insufficient-scope`, naming the scopes the
    operation needed. Read and run are separate throughout, so a credential can
    be allowed to read results without being allowed to spend money producing
    them.


    `chronology:read`, `chronology:write`, `clients:read`, `clients:write`,
    `compare:read`, `compare:run`, `compliance:read`, `compliance:run`,
    `credentials:rotate`, `documents:download`, `documents:read`,
    `documents:write`, `drafting:read`, `drafting:run`, `exports:create`,
    `exports:read`, `facts:read`, `facts:run`, `matrices:read`, `matrices:run`,
    `matrices:write`, `matters:read`, `matters:write`, `nda:read`, `nda:run`,
    `operations:read`, `playbooks:read`, `playbooks:run`, `playbooks:write`,
    `research:read`, `research:run`, `review:read`, `review:run`,
    `summaries:read`, `summaries:run`, `webhooks:read`, `webhooks:write`,
    `workflows:read`, `workflows:run`, `workflows:write`
  version: 1.0.0
servers:
  - url: https://api.vaquill.ai/workspace
    description: Vaquill Legal Workspace API (production)
  - url: /workspace
    description: Vaquill Legal Workspace API (relative to the mount)
security:
  - WorkspaceAuth: []
tags:
  - name: Operations
    description: >-
      The one job envelope. Every long-running call answers `202` with an
      operation, and polling this resource is the only way to learn it finished:
      there are no webhooks. Five statuses, no synonyms.
  - name: Clients
    description: The people and companies matters are filed under. Synchronous CRUD.
  - name: Matters
    description: >-
      The unit of work everything else hangs off. A matter scopes documents,
      drafts, reviews, comparisons and matrices, and it is what a credential's
      access is checked against.
  - name: Folders
    description: >-
      Organization inside and across matters. The same folders the web app
      shows, so one created here appears in the customer's browser.
  - name: Documents
    description: >-
      Files in a matter: their metadata, their ingested text, and the original
      bytes. A document is only usable by retrieval, drafting and review once
      its status is `succeeded`.
  - name: Uploads
    description: >-
      Getting files in. One presigned multipart flow at every size, with the
      bytes going straight to storage and never through this API. Initiate, PUT
      each part, then complete.
  - name: Research
    description: >-
      Asking legal questions and getting grounded, cited answers. This API does
      NOT stream: an ask answers `202` and you poll the operation, then read the
      answer off the message it points at. Conversation state is kept here, so
      you hold a chat id rather than replaying a transcript. Also covers the
      matter settings behind an answer, the skills you can ask through, and the
      standalone web-research tools.
  - name: Drafting
    description: >-
      Generating, revising and exporting draft documents. Bodies come out as
      sections and go in as markdown; the editor's own format is never on the
      wire. Rendered files come from the export route.
  - name: Playbooks
    description: >-
      The organization's negotiating positions, per contract type, and the
      starter templates to build them from. A playbook is the input a contract
      review is measured against.
  - name: Reviews
    description: >-
      Reviewing one contract against a playbook: clause analysis, redlines,
      flags, liability exposure and a reported sign-off gate. Export applies the
      redlines as native Word tracked changes.
  - name: Facts
    description: >-
      The cross-document fact ledger for a matter: what every document in it
      asserts, coalesced and cited back to its source passages.
  - name: Matter summary
    description: >-
      A citation-backed summary of everything filed to a matter, generated on
      demand and readable claim by claim.
  - name: Chronology
    description: >-
      The dated events across a matter's documents, as one timeline, with
      duplicate and date-conflict flags.
  - name: NDA triage
    description: >-
      Screening one inbound NDA against ten standard criteria and, where you
      name one, your own NDA playbook. Answers `green`, `yellow` or `red` with
      the reasoning per criterion, plus a report you can forward.
  - name: Compliance
    description: >-
      Checking one document against one regulation's requirement checklist: a
      verdict per requirement with the article it comes from, the gaps, and what
      to do about them. Only regulations with a real checklist behind them are
      accepted.
  - name: Comparisons
    description: >-
      Diffing two documents in a matter into structural changes, with a
      substantive-versus-cosmetic judgment and a downloadable redline.
  - name: Matrices
    description: >-
      Spreadsheet-style extraction across many documents: rows are documents,
      columns are questions, cells are answers with verified citations. Building
      a grid is free; running it is what costs.
  - name: Workflows
    description: >-
      Multi-step analyses from a fixed catalogue. Read a definition to learn
      what documents and inputs it takes, launch a run inside a matter, then
      download the artifacts it produces.
externalDocs:
  description: Getting started guide and error reference
  url: https://vaquill.ai/docs/workspace-api
paths:
  /v1/matters/{matterId}/matrices:
    post:
      tags:
        - Matrices
      summary: Create a matrix
      description: >-
        Build a grid. Nothing is extracted until you run it.


        Rows are documents and columns are questions, so the grid is `documents
        x

        columns` cells and each cell is one billable extraction when the matrix
        is

        run. Every document must already be in this matter and finished
        ingesting:

        a still-ingesting document is refused, because retrieval over it would

        answer "not in this document" for every column.


        Note the column vocabulary: `free_text`, `single_select`, `date`,
        `money`,

        `yes_no`, `party_name`. There is no `text`, `number` or `boolean`.
      operationId: matrices.create
      parameters:
        - name: matterId
          in: path
          required: true
          schema:
            type: string
            title: Matterid
          description: >-
            `mat_` identifier of the matter to work inside. Everything in this
            API hangs off a matter, and the matter in the path is what the
            authorization boundary is checked against. Take it from `GET
            /v1/matters`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MatrixCreateRequest'
            example:
              title: Vendor agreement review
              description: >-
                Master services agreement with Acme for the 2026 platform
                rollout.
              documentIds:
                - value
              columns:
                - label: Liability cap
                  question: What is the liability cap, and what does it apply to?
                  columnType: free_text
                  options:
                    - 'yes'
                    - 'no'
                    - not addressed
                  instructions: >-
                    House paper. Cap liability at 12 months of fees; never
                    accept uncapped indemnity.
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Matrix'
              example:
                id: mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
                matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
                title: Vendor agreement review
                description: >-
                  Master services agreement with Acme for the 2026 platform
                  rollout.
                status: succeeded
                columns:
                  - id: col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
                    label: Liability cap
                    question: What is the liability cap, and what does it apply to?
                    columnType: free_text
                    options:
                      - 'yes'
                      - 'no'
                      - not addressed
                    instructions: >-
                      House paper. Cap liability at 12 months of fees; never
                      accept uncapped indemnity.
                    dependsOnColumnId: col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
                    gateExpression: 'yes'
                    injectUpstream: false
                    position: 0
                rows:
                  - id: row_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
                    documentId: doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
                    filename: msa-acme-v3.docx
                    position: 0
                cellCount: 24
                pendingCellCount: 0
                errorCellCount: 0
                createdAt: '2026-08-19T14:32:10Z'
                updatedAt: '2026-08-19T14:32:10Z'
        '401':
          description: >-
            The credential is missing, malformed, unknown, revoked or expired.
            `type` is `invalid-credential`, or `wrong-product-credential` when a
            `vq_key_` Data API key was sent to this API.
          headers:
            X-Request-ID:
              description: >-
                The id of this request. The same value appears as `requestId` in
                the body. Quote it when contacting support.
              schema:
                type: string
                examples:
                  - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
            WWW-Authenticate:
              description: RFC 9110 authentication challenge.
              schema:
                type: string
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: >-
            The credential does not carry a scope this operation requires
            (`insufficient-scope`), or the organization's installation is
            suspended (`installation-inactive`).
          headers:
            X-Request-ID:
              description: >-
                The id of this request. The same value appears as `requestId` in
                the body. Quote it when contacting support.
              schema:
                type: string
                examples:
                  - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
            WWW-Authenticate:
              description: RFC 9110 authentication challenge.
              schema:
                type: string
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: >-
            The resource does not exist, is not this organization's, or is
            outside this installation's matter allowlist. The three are
            deliberately indistinguishable, so the status code cannot be used to
            discover which ids exist in another organization. Each resource has
            its own `type`.
          headers:
            X-Request-ID:
              description: >-
                The id of this request. The same value appears as `requestId` in
                the body. Quote it when contacting support.
              schema:
                type: string
                examples:
                  - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: >-
            The request does not match the published schema. `errors` names each
            rejected field and why. The submitted value is never echoed back.
          headers:
            X-Request-ID:
              description: >-
                The id of this request. The same value appears as `requestId` in
                the body. Quote it when contacting support.
              schema:
                type: string
                examples:
                  - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ValidationProblem'
        '429':
          description: Too many requests for this credential's tier. Honour `Retry-After`.
          headers:
            X-Request-ID:
              description: >-
                The id of this request. The same value appears as `requestId` in
                the body. Quote it when contacting support.
              schema:
                type: string
                examples:
                  - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: >-
            An unexpected error on our side. The body carries a stable `type`
            and the request id and nothing else; the cause is in our logs.
          headers:
            X-Request-ID:
              description: >-
                The id of this request. The same value appears as `requestId` in
                the body. Quote it when contacting support.
              schema:
                type: string
                examples:
                  - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '503':
          description: >-
            A dependency this request needs is unavailable, so nothing was done.
            Retryable. Authentication fails closed rather than admitting the
            request, so this is never a statement about your credential.
          headers:
            X-Request-ID:
              description: >-
                The id of this request. The same value appears as `requestId` in
                the body. Quote it when contacting support.
              schema:
                type: string
                examples:
                  - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
components:
  schemas:
    MatrixCreateRequest:
      properties:
        title:
          type: string
          maxLength: 300
          minLength: 1
          title: Title
          description: Display title for the matrix.
          examples:
            - Vendor agreement review
        description:
          anyOf:
            - type: string
              maxLength: 2000
            - type: 'null'
          title: Description
          description: Free-text description of what the matrix is for.
          examples:
            - Master services agreement with Acme for the 2026 platform rollout.
        documentIds:
          items:
            type: string
          type: array
          title: Documentids
          description: >-
            `doc_` identifiers that become the rows, one row per document. Each
            must be in this matter and must have finished ingesting. Duplicates
            are refused rather than de-duplicated.
          examples:
            - - value
        columns:
          items:
            $ref: '#/components/schemas/MatrixColumnSpec'
          type: array
          maxItems: 60
          title: Columns
          description: >-
            The questions asked of every document, one column each. At most 60.
            Documents times columns is the number of billable extractions a run
            performs.
      additionalProperties: false
      type: object
      required:
        - title
      title: MatrixCreateRequest
      description: Build a grid. Nothing is extracted until `matrices.run`.
    Matrix:
      properties:
        id:
          type: string
          title: Id
          description: Public identifier, `mtx_` followed by 32 hex characters.
          examples:
            - mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        matterId:
          type: string
          title: Matterid
          description: '`mat_` identifier of the matter this matrix belongs to.'
          examples:
            - mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        title:
          type: string
          title: Title
          description: Display title for the matrix.
          examples:
            - Vendor agreement review
        description:
          anyOf:
            - type: string
            - type: 'null'
          title: Description
          description: Free-text description of what the matrix is for.
          examples:
            - Master services agreement with Acme for the 2026 platform rollout.
        status:
          $ref: '#/components/schemas/OperationStatus'
          description: Matrix status, using the same five public values as an operation.
          examples:
            - succeeded
        columns:
          items:
            $ref: '#/components/schemas/MatrixColumn'
          type: array
          title: Columns
          description: >-
            Every column, inlined. A cell names only ids, so these are what make
            one readable.
        rows:
          items:
            $ref: '#/components/schemas/MatrixRow'
          type: array
          title: Rows
          description: Every row, inlined, one per document.
        cellCount:
          type: integer
          title: Cellcount
          description: Total cells in the grid, which is rows times columns.
          default: 0
          examples:
            - 24
        pendingCellCount:
          type: integer
          title: Pendingcellcount
          description: >-
            Cells that have not produced an answer yet. Zero means extraction is
            complete.
          default: 0
          examples:
            - 0
        errorCellCount:
          type: integer
          title: Errorcellcount
          description: >-
            Cells whose extraction failed. These are distinct from cells that
            succeeded with a null answer.
          default: 0
          examples:
            - 0
        createdAt:
          type: string
          format: date-time
          title: Createdat
          description: When the matrix was created (RFC 3339).
          examples:
            - '2026-08-19T14:32:10Z'
        updatedAt:
          type: string
          format: date-time
          title: Updatedat
          description: When the matrix was last updated (RFC 3339).
          examples:
            - '2026-08-19T14:32:10Z'
      additionalProperties: false
      type: object
      required:
        - id
        - matterId
        - title
        - status
        - createdAt
        - updatedAt
      title: Matrix
      description: >-
        The grid header plus its axes. Cells are a separate, paged read.


        Rows and columns are inlined because they are bounded and because a cell
        is

        unreadable without them: a cell names a row id and a column id and
        nothing

        else, so a client that could not resolve those would have to page the
        whole

        grid to interpret one answer.
    Problem:
      type: object
      title: Problem
      description: >-
        An RFC 9457 problem document. Branch on `type`, which is stable; `title`
        and `detail` are written for people and may be reworded. Some problems
        carry extra members (`requiredScopes`, `limit`, `expectedVersion`),
        which is why this object is open.
      required:
        - type
        - title
        - status
        - detail
        - instance
      properties:
        type:
          type: string
          format: uri
          description: >-
            The stable identifier for this error, and the one field to branch
            on. Resolves to a page describing it.
          examples:
            - https://vaquill.ai/docs/workspace-api/errors/insufficient-scope
        title:
          type: string
          description: A short human-readable summary.
          examples:
            - Insufficient scope
        status:
          type: integer
          description: The HTTP status code, repeated.
          examples:
            - 403
        detail:
          type: string
          description: >-
            What went wrong on this specific request. May be reworded at any
            time.
          examples:
            - >-
              This credential carries matters:read. This operation needs
              matters:write.
        instance:
          type: string
          description: The path this problem occurred on.
          examples:
            - /workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        requestId:
          type: string
          description: >-
            The id of this request, identical to the `X-Request-ID` response
            header. Quote it when contacting support.
          examples:
            - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
      additionalProperties: true
    ValidationProblem:
      type: object
      title: ValidationProblem
      description: >-
        A problem document for a schema rejection. `errors` lists the fields
        that were refused. The value you submitted is deliberately not echoed,
        so a validation failure cannot copy your content into an error response
        or into either side's logs.
      required:
        - type
        - title
        - status
        - detail
        - instance
        - errors
      properties:
        type:
          type: string
          format: uri
          description: >-
            The stable identifier for this error, and the one field to branch
            on. Resolves to a page describing it.
          examples:
            - https://vaquill.ai/docs/workspace-api/errors/insufficient-scope
        title:
          type: string
          description: A short human-readable summary.
          examples:
            - Insufficient scope
        status:
          type: integer
          description: The HTTP status code, repeated.
          examples:
            - 403
        detail:
          type: string
          description: >-
            What went wrong on this specific request. May be reworded at any
            time.
          examples:
            - >-
              This credential carries matters:read. This operation needs
              matters:write.
        instance:
          type: string
          description: The path this problem occurred on.
          examples:
            - /workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        requestId:
          type: string
          description: >-
            The id of this request, identical to the `X-Request-ID` response
            header. Quote it when contacting support.
          examples:
            - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        errors:
          type: array
          description: One entry per rejected field.
          items:
            type: object
            required:
              - location
              - message
              - type
            properties:
              location:
                type: string
                description: >-
                  Dotted path to the rejected field, for example
                  `body.contentMarkdown`.
              message:
                type: string
                description: Why it was rejected.
              type:
                type: string
                description: The validation rule that failed.
      additionalProperties: true
    MatrixColumnSpec:
      properties:
        label:
          type: string
          maxLength: 200
          minLength: 1
          title: Label
          description: Short column heading, as it appears across the top of the grid.
          examples:
            - Liability cap
        question:
          type: string
          maxLength: 4000
          minLength: 1
          title: Question
          description: >-
            The question asked of every document in the matrix. This is the
            prompt the extractor runs per cell, so be specific about what counts
            as an answer.
          examples:
            - What is the liability cap, and what does it apply to?
        columnType:
          type: string
          enum:
            - free_text
            - single_select
            - date
            - money
            - yes_no
            - party_name
          title: Columntype
          description: >-
            What shape of answer to ask for. Note the vocabulary: `free_text`,
            `single_select`, `date`, `money`, `yes_no`, `party_name`. There is
            no `text`, `number` or `boolean`.
          default: free_text
          examples:
            - free_text
        options:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Options
          description: >-
            Allowed answers, required when `columnType` is `single_select` and
            ignored otherwise.
          examples:
            - - 'yes'
              - 'no'
              - not addressed
        instructions:
          anyOf:
            - type: string
              maxLength: 4000
            - type: 'null'
          title: Instructions
          description: >-
            Extra guidance for the extractor on this column only, for example
            how to handle a missing value.
          examples:
            - >-
              House paper. Cap liability at 12 months of fees; never accept
              uncapped indemnity.
      additionalProperties: false
      type: object
      required:
        - label
        - question
      title: MatrixColumnSpec
      description: >-
        One question asked of every document in the matrix.


        Conditional columns (`dependsOnColumnId`, `gateExpression`,

        `injectUpstream`) are not published HERE, and the reason is narrower
        than it

        used to be. They key on a column id that does not exist until the create

        returns, so a dependency cannot be expressed in the same call that mints

        both columns without inventing a client-side reference scheme.


        They ARE published on `matrices.updateColumn`

        (`contracts/models/matrix_edits.MatrixColumnPatch`), where the caller
        names

        a `col_` id it read off a `Matrix` response, which is an ordinary

        caller-supplied reference. That is the two-pass shape the product
        already

        uses internally: `MatrixService._wire_template_dependencies` creates the

        columns and then patches the edges, and a customer does the same thing
        with

        two calls.
    OperationStatus:
      type: string
      enum:
        - queued
        - running
        - succeeded
        - failed
        - cancelled
      title: OperationStatus
      description: >-
        The public five. There is no sixth, and there are no synonyms.


        Internal vocabularies spell terminal success `completed`, `ready`,

        `extracted`, `succeeded` and `fresh`; terminal failure `failed` and
        `error`;

        queued `pending`, `queued` and `draft`. All of that is collapsed here by

        `app.workspace_api.adapters.status_map`, which refuses to guess.
    MatrixColumn:
      properties:
        id:
          type: string
          title: Id
          description: >-
            Public identifier for the column, `col_` followed by 32 hex
            characters. Cells reference it as `columnId`.
          examples:
            - col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        label:
          type: string
          title: Label
          description: Column heading.
          examples:
            - Liability cap
        question:
          type: string
          title: Question
          description: The question asked of every document in this column.
          examples:
            - What is the liability cap, and what does it apply to?
        columnType:
          type: string
          title: Columntype
          description: >-
            What shape of answer this column asks for. Published as a plain
            string, since production predates this API.
          examples:
            - free_text
        options:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Options
          description: Allowed answers for a select column.
          examples:
            - - 'yes'
              - 'no'
              - not addressed
        instructions:
          anyOf:
            - type: string
            - type: 'null'
          title: Instructions
          description: Extra extractor guidance scoped to this column.
          examples:
            - >-
              House paper. Cap liability at 12 months of fees; never accept
              uncapped indemnity.
        dependsOnColumnId:
          anyOf:
            - type: string
            - type: 'null'
          title: Dependsoncolumnid
          description: >-
            `col_` identifier of the column this one is conditional on, or null
            when it always runs.
          examples:
            - col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        gateExpression:
          anyOf:
            - type: string
            - type: 'null'
          title: Gateexpression
          description: >-
            The condition on the upstream answer that has to hold for this
            column to run. Null means it always runs when its dependency has
            answered.
          examples:
            - 'yes'
        injectUpstream:
          type: boolean
          title: Injectupstream
          description: >-
            Whether the upstream column's answer is prepended to this column's
            prompt.
          default: false
          examples:
            - false
        position:
          type: integer
          title: Position
          description: >-
            Left-to-right position of the column in the grid. Ascending, and not
            necessarily contiguous: deleting a column leaves a gap rather than
            renumbering.
          examples:
            - 0
      additionalProperties: false
      type: object
      required:
        - id
        - label
        - question
        - columnType
        - position
      title: MatrixColumn
      description: One column of the grid, as stored.
    MatrixRow:
      properties:
        id:
          type: string
          title: Id
          description: >-
            Public identifier for the row, `row_` followed by 32 hex characters.
            Cells reference it as `rowId`.
          examples:
            - row_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        documentId:
          type: string
          title: Documentid
          description: '`doc_` identifier of the document this row represents.'
          examples:
            - doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6
        filename:
          anyOf:
            - type: string
            - type: 'null'
          title: Filename
          description: Filename of that document, joined in for display.
          examples:
            - msa-acme-v3.docx
        position:
          type: integer
          title: Position
          description: >-
            Top-to-bottom position of the row in the grid. Ascending, and not
            necessarily contiguous: deleting a row leaves a gap rather than
            renumbering.
          examples:
            - 0
      additionalProperties: false
      type: object
      required:
        - id
        - documentId
        - position
      title: MatrixRow
      description: One document in the grid.
  securitySchemes:
    WorkspaceAuth:
      type: http
      scheme: bearer
      bearerFormat: vq_ws_*
      description: >-
        Workspace credential issued from the automation console at
        `/automation`. Send it as `Authorization: Bearer vq_ws_...`. This is NOT
        a Data API key: a `vq_key_` credential is refused here and names the
        other product in the error.

````