openapi: 3.2.0 info: title: Vaquill Ai Drafting API version: 1.0.0 description: 'Operations tagged Drafting across 2 of this provider''s published API definitions: vaquill-ai-workspace-openapi.json, vaquill-ai-workspace-openapi.yml. Each path carries the servers of the definition it was published in.' 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: 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. paths: /v1/draft-categories: get: tags: - Drafting summary: List drafting categories description: 'Every document type `drafts.generate` will write, alphabetically. Send an `id` from here as `category`. Each entry carries the product''s own name for the document type and the practice area a draft in it is filed under. The list is what we advertise, and the validator is slightly wider than it: a draft that already exists in a category this list omits can still be revised. New categories appear here without a version change, so read it rather than pinning a copy. `principal` is unused for filtering and is still required: the route is credential-gated like every other, and taking the principal is what makes that visible at the handler rather than only in the policy.' operationId: draftCategories.list parameters: - name: limit in: query required: false schema: type: integer maximum: 200 minimum: 1 description: How many rows to return, 1 to 200. Defaults to 50. default: 50 title: Limit description: How many rows to return, 1 to 200. Defaults to 50. - name: offset in: query required: false schema: type: integer minimum: 0 description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' default: 0 title: Offset description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Page_DraftCategory_' example: data: - id: nda label: Liability cap practiceArea: commercial pagination: limit: 50 offset: 0 total: 128 hasMore: false '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts: get: tags: - Drafting summary: List drafts in a matter description: 'Every draft in this matter, newest edit first, without their bodies. Two status fields, and they are not the same thing. `status` is where the DOCUMENT is in its lifecycle and you set it. `generationStatus` is where the JOB that produced it got to, and only the pipeline sets it. Fetch a draft by id to get its body. Pass `state=trashed` to list what has been deleted and is still restorable. Deleted drafts are invisible to every other read on this API, so this is the only way to find one whose id you no longer hold.' operationId: drafts.list 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`.' - name: limit in: query required: false schema: type: integer maximum: 200 minimum: 1 description: How many rows to return, 1 to 200. Defaults to 50. default: 50 title: Limit description: How many rows to return, 1 to 200. Defaults to 50. - name: offset in: query required: false schema: type: integer minimum: 0 description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' default: 0 title: Offset description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' - name: state in: query required: false schema: enum: - active - trashed type: string description: 'Which drafts to list: `active` (the default) or `trashed`. A trashed draft is restorable for 30 days and is invisible to every other read on this API.' default: active title: State description: 'Which drafts to list: `active` (the default) or `trashed`. A trashed draft is restorable for 30 days and is invisible to every other read on this API.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Page_DraftSummary_' example: data: - id: drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement category: commercial practiceArea: commercial status: draft source: generated version: 3 generationStatus: succeeded governingLawState: ca createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' pagination: limit: 50 offset: 0 total: 128 hasMore: false '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' '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' '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' post: tags: - Drafting summary: Generate a draft description: 'Queue a generation. 202 with an operation to poll. A retry carrying the same `Idempotency-Key` returns the original operation and starts nothing. That is what makes a client timeout free rather than a second billed generation, and it matters more here than anywhere else on this surface: `run_draft_generation_task` has `max_retries=0` precisely because the pipeline is not idempotent.' operationId: drafts.generate 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`.' - name: Idempotency-Key in: header required: false schema: anyOf: - type: string - type: 'null' title: Idempotency-Key description: A unique value of your choosing, so a retried launch returns the FIRST operation instead of starting a second billable job. Reusing one with a different body is refused. Retrying with the same key and the same body is free and is the intended way to recover from a timeout. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DraftCreateRequest' example: category: commercial title: Master Services Agreement governingLawState: ca tone: protective specialInstructions: Two-year term, mutual, governed by California law. variables: party_a_name: value practiceArea: commercial responses: '202': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Operation' example: id: op_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 type: matrix.run status: succeeded createdAt: '2026-08-19T14:32:10Z' completedAt: '2026-08-19T14:32:10Z' matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 resource: kind: matrix id: mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 url: https://storage.vaquill.ai/exports/msa-acme-v3-redline.docx?signature=... progress: done: 24 total: 128 unit: cells requestId: req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/from-document: post: tags: - Drafting summary: Create a draft from an uploaded document description: 'Turn a document in this matter into an editable draft. Upload the file first through `uploads.initiate`, then name the `documentId` the completed upload produced. The ORIGINAL file is converted, not the text the ingest pipeline extracted for retrieval: that text is chunk-shaped and has already lost the headings a contract is navigated by. `201` with the draft rather than `202` with an operation, because no model runs. This is a format conversion. A `.docx` keeps its headings, lists and tables. `.txt` and `.md` are converted paragraph by paragraph. Anything else is refused rather than degraded.' operationId: drafts.createFromDocument 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/DraftFromDocumentRequest' example: documentId: doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement category: commercial responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Draft' example: id: drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement category: commercial practiceArea: commercial status: draft source: generated version: 3 generationStatus: succeeded governingLawState: ca createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/{draftId}: get: tags: - Drafting summary: Get a draft description: 'One draft, section by section. The body comes back as `sections` rather than as the editor''s own document model, and edits go back in as `contentMarkdown`. For a rendered DOCX or PDF use the export route instead. A `404` covers every reason it is not readable: no such id, another organization''s, another matter''s, or binned.' operationId: drafts.get 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Draft' example: id: drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement category: commercial practiceArea: commercial status: draft source: generated version: 3 generationStatus: succeeded governingLawState: ca createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' put: tags: - Drafting summary: Replace a draft's body description: 'Replace a draft''s body, keeping the previous one as a version. A PUT, not a PATCH: `contentMarkdown` is the WHOLE body, so sending one paragraph replaces the document with that paragraph. Pass `expectedVersion` with the version you read to make this a safe read-modify-write; omitting it means "overwrite whatever is there". Title and status are left alone when omitted.' operationId: drafts.update 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DraftReplaceRequest' example: contentMarkdown: '# Mutual Non-Disclosure Agreement ## 1. Confidential Information Each party may disclose information that is confidential and proprietary to the other party. ' title: Master Services Agreement status: draft changeSummary: Tightened the indemnity carve-outs after counsel review. expectedVersion: 1 responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Draft' example: id: drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement category: commercial practiceArea: commercial status: draft source: generated version: 3 generationStatus: succeeded governingLawState: ca createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' delete: tags: - Drafting summary: Move a draft to the trash description: 'Move a draft to the trash. It stops being listed, stops being readable and stops being exportable through this API. It is restorable for **30 days**, after which it is permanently removed and `drafts.restore` answers `404`. List what is in the trash with `state=trashed`. Version history is preserved for as long as the draft is. That is why this is not a permanent delete: the history and the `draftId` on any template run that produced this draft both hang off the row, and removing it would take them with it. Not idempotent. Deleting the same draft twice answers `404` the second time, so on a delete that timed out, treat a subsequent `404` as success.' operationId: drafts.delete 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' responses: '204': description: Successful Response '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/{draftId}/improvements: post: tags: - Drafting summary: Revise a draft into a new one description: 'Queue a revision. 202 with an operation whose resource is a NEW draft. The improvement never overwrites its source, which is the internal pipeline''s behaviour and the right one to publish: the run takes minutes and costs money, and a customer that dislikes the result still holds the draft it started from.' operationId: drafts.improve 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' - name: Idempotency-Key in: header required: false schema: anyOf: - type: string - type: 'null' title: Idempotency-Key description: A unique value of your choosing, so a retried launch returns the FIRST operation instead of starting a second billable job. Reusing one with a different body is refused. Retrying with the same key and the same body is free and is the intended way to recover from a timeout. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DraftImproveRequest' example: instructions: House paper. Cap liability at 12 months of fees; never accept uncapped indemnity. category: commercial tone: protective responses: '202': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Operation' example: id: op_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 type: matrix.run status: succeeded createdAt: '2026-08-19T14:32:10Z' completedAt: '2026-08-19T14:32:10Z' matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 resource: kind: matrix id: mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 url: https://storage.vaquill.ai/exports/msa-acme-v3-redline.docx?signature=... progress: done: 24 total: 128 unit: cells requestId: req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/{draftId}/versions: get: tags: - Drafting summary: List a draft's versions description: 'A draft''s version history, newest first. Metadata only. The stored content of an old version is deliberately not published, so this is an audit trail rather than a way to read the document back at a point in time. `changeSummary` is whatever was supplied on the replace that created each version.' operationId: drafts.versions 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' - name: limit in: query required: false schema: type: integer maximum: 200 minimum: 1 description: How many rows to return, 1 to 200. Defaults to 50. default: 50 title: Limit description: How many rows to return, 1 to 200. Defaults to 50. - name: offset in: query required: false schema: type: integer minimum: 0 description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' default: 0 title: Offset description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Page_DraftVersion_' example: data: - version: 3 changeSummary: Tightened the indemnity carve-outs after counsel review. createdAt: '2026-08-19T14:32:10Z' pagination: limit: 50 offset: 0 total: 128 hasMore: false '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/{draftId}/exports: post: tags: - Drafting summary: Export a draft as DOCX or PDF description: 'Render the draft to DOCX or PDF and return the bytes. A POST rather than a GET because it produces something that did not exist: the file is rendered per call rather than fetched, and recording that as a creation is what lets an audit answer who took a copy and when.' operationId: drafts.export 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DraftExportRequest' example: format: docx responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DraftExport' example: format: docx filename: msa-acme-v3.docx sizeBytes: 248193 content: UEsDBBQABgAIAAAAIQ... unfilledPlaceholders: 0 '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/{draftId}/copies: post: tags: - Drafting summary: Copy a draft description: 'Copy a draft into the same matter. Send `{}` to accept the defaults. The copy starts at version 1 with no history of its own and status `draft`. Comment marks are removed, because a comment anchors to a thread that belongs to the original and would render in your editor as a highlight pointing at nothing. Tracked-change marks are kept.' operationId: drafts.duplicate 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DraftCopyRequest' example: title: Master Services Agreement responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Draft' example: id: drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement category: commercial practiceArea: commercial status: draft source: generated version: 3 generationStatus: succeeded governingLawState: ca createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/{draftId}/restore: post: tags: - Drafting summary: Restore a trashed draft description: 'Bring a trashed draft back, inside the 30-day window. A draft that is not in the trash answers `404`, so this is safe to call without checking first: it either restores something or tells you there was nothing to restore. Past the window the row is gone and the answer is the same `404`.' operationId: drafts.restore 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Draft' example: id: drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement category: commercial practiceArea: commercial status: draft source: generated version: 3 generationStatus: succeeded governingLawState: ca createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/drafts/{draftId}/documents: post: tags: - Drafting summary: File a draft into its matter as a document description: 'File the draft into its matter as a DOCX document. Answers `202` with a `document.ingest` operation, the same kind and the same envelope `uploads.complete` returns, so a caller that already polls an ingest has nothing new to learn. Poll it, then read `resource.id` for the `documentId`. The document lands in the draft''s own matter, the one in this path. To file it elsewhere, duplicate the draft into the target matter first. The draft is not changed and not consumed: filing it produces a second, independent thing, and editing the draft afterwards does not alter the document.' operationId: drafts.saveAsDocument 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`.' - name: draftId in: path required: true schema: type: string title: Draftid description: '`drf_` identifier of the draft. Take it from the matter''s draft list.' - name: Idempotency-Key in: header required: false schema: anyOf: - type: string - type: 'null' title: Idempotency-Key description: A unique value of your choosing, so a retried launch returns the FIRST operation instead of starting a second billable job. Reusing one with a different body is refused. Retrying with the same key and the same body is free and is the intended way to recover from a timeout. responses: '202': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Operation' example: id: op_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 type: matrix.run status: succeeded createdAt: '2026-08-19T14:32:10Z' completedAt: '2026-08-19T14:32:10Z' matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 resource: kind: matrix id: mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 url: https://storage.vaquill.ai/exports/msa-acme-v3-redline.docx?signature=... progress: done: 24 total: 128 unit: cells requestId: req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/templates: get: tags: - Drafting summary: List templates description: 'Every active template this organization owns. Our own starter templates are not listed. They belong to us rather than to you, and a template you did not author is not one your automation should be running as if you had.' operationId: templates.list parameters: - name: limit in: query required: false schema: type: integer maximum: 200 minimum: 1 description: How many rows to return, 1 to 200. Defaults to 50. default: 50 title: Limit description: How many rows to return, 1 to 200. Defaults to 50. - name: offset in: query required: false schema: type: integer minimum: 0 description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' default: 0 title: Offset description: 'How many rows to skip before returning any. Combine with `limit` to page: `offset=0`, then `offset=50`, and so on. Offsets are positional, not stable, so a set that changes while you page can show a row twice or not at all.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Page_Template_' example: data: - id: tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Mutual NDA description: Master services agreement with Acme for the 2026 platform rollout. category: commercial sourceFilename: msa-acme-v3.docx createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' pagination: limit: 50 offset: 0 total: 128 hasMore: false '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' '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' '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' post: tags: - Drafting summary: Create a template from markdown description: 'Author a template from markdown. Fillable spans are detected as part of this call and returned in `variables`, so a template created here can never be one that runs and interpolates nothing. Detection is a deterministic regex pass over the text: `[BRACKETED PLACEHOLDERS]`, `{{jinja_fields}}`, `>`, runs of underscores, dates, amounts and durations. The product also runs an LLM refinement pass over an upload and this API does not, so a template created here may carry fewer variables than the same text imported in the browser.' operationId: templates.create requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TemplateCreateRequest' example: title: Mutual NDA contentMarkdown: '# Mutual Non-Disclosure Agreement ## 1. Confidential Information Each party may disclose information that is confidential and proprietary to the other party. ' description: Master services agreement with Acme for the 2026 platform rollout. category: commercial responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TemplateDetail' example: id: tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement description: Master services agreement with Acme for the 2026 platform rollout. category: commercial sourceFilename: msa-acme-v3.docx createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' variables: - id: party_a_name name: Counterparty name label: Counterparty name kind: matrix hint: value defaultValue: value position: 0 sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/templates/from-document: post: tags: - Drafting summary: Create a template from an uploaded document description: 'Turn a document you already uploaded into a template. Upload the file first through `uploads.initiate`, then name the `documentId` the completed upload produced. The source document stays yours: you can list, download and delete it, which is what makes "which contract did this template come from" answerable months later. A `.docx` keeps its headings, lists and tables. `.txt` and `.md` are converted paragraph by paragraph. Anything else is refused rather than degraded, because an import that silently lost its structure is one nobody notices until they open the result.' operationId: templates.createFromDocument requestBody: content: application/json: schema: $ref: '#/components/schemas/TemplateFromDocumentRequest' example: documentId: doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement description: Master services agreement with Acme for the 2026 platform rollout. category: commercial required: true responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TemplateDetail' example: id: tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement description: Master services agreement with Acme for the 2026 platform rollout. category: commercial sourceFilename: msa-acme-v3.docx createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' variables: - id: party_a_name name: Counterparty name label: Counterparty name kind: matrix hint: value defaultValue: value position: 0 sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/templates/{templateId}: get: tags: - Drafting summary: Get a template description: 'One template, including the `varId`s a run''s `slotOverrides` accepts. This is where you learn a template''s keys. Without it the only way to find them is to run the template once and read the slots back off the finished run, which is a paid generation spent discovering a schema. `sections` is the body as plain text with the placeholders still in it, so you can read what the template says before deciding to run it.' operationId: templates.get parameters: - name: templateId in: path required: true schema: type: string title: Templateid description: '`tpl_` identifier of one of your uploaded draft templates. Take it from `GET /v1/templates`.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TemplateDetail' example: id: tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement description: Master services agreement with Acme for the 2026 platform rollout. category: commercial sourceFilename: msa-acme-v3.docx createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' variables: - id: party_a_name name: Counterparty name label: Counterparty name kind: matrix hint: value defaultValue: value position: 0 sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' put: tags: - Drafting summary: Replace a template's body description: 'Replace a template''s body, re-detecting its variables. A PUT, not a PATCH: `contentMarkdown` is the whole body, so sending one clause replaces the template with that clause. Title and description are left alone when omitted. **This is lossy against a template imported from a `.docx`.** Word formatting the importer preserved cannot be expressed in markdown and is discarded. Duplicate the template first if you want to keep the original.' operationId: templates.update parameters: - name: templateId in: path required: true schema: type: string title: Templateid description: '`tpl_` identifier of one of your uploaded draft templates. Take it from `GET /v1/templates`.' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TemplateUpdateRequest' example: contentMarkdown: '# Mutual Non-Disclosure Agreement ## 1. Confidential Information Each party may disclose information that is confidential and proprietary to the other party. ' title: Mutual NDA description: Master services agreement with Acme for the 2026 platform rollout. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TemplateDetail' example: id: tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement description: Master services agreement with Acme for the 2026 platform rollout. category: commercial sourceFilename: msa-acme-v3.docx createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' variables: - id: party_a_name name: Counterparty name label: Counterparty name kind: matrix hint: value defaultValue: value position: 0 sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' delete: tags: - Drafting summary: Delete a template description: 'Retire a template. It stops being listed, stops being runnable and stops being readable through this API, and this API will never bring it back. Runs that already used it keep working: a template run records what it produced, and destroying those records to delete the template would rewrite history a customer may still be relying on. Not idempotent. Deleting the same template twice answers `404` the second time, so on a delete that timed out, treat a subsequent `404` as success.' operationId: templates.delete parameters: - name: templateId in: path required: true schema: type: string title: Templateid description: '`tpl_` identifier of one of your uploaded draft templates. Take it from `GET /v1/templates`.' responses: '204': description: Successful Response '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/templates/{templateId}/copies: post: tags: - Drafting summary: Copy a template description: 'Copy a template under a new id. Send `{}` to accept the defaults. The copy is a separate template with its own variables, so editing it cannot touch the original. That makes it the safe move before replacing the body of a template imported from a `.docx`.' operationId: templates.duplicate parameters: - name: templateId in: path required: true schema: type: string title: Templateid description: '`tpl_` identifier of one of your uploaded draft templates. Take it from `GET /v1/templates`.' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TemplateCopyRequest' example: title: Master Services Agreement responses: '201': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TemplateDetail' example: id: tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: Master Services Agreement description: Master services agreement with Acme for the 2026 platform rollout. category: commercial sourceFilename: msa-acme-v3.docx createdAt: '2026-08-19T14:32:10Z' updatedAt: '2026-08-19T14:32:10Z' variables: - id: party_a_name name: Counterparty name label: Counterparty name kind: matrix hint: value defaultValue: value position: 0 sections: - heading: 8. Limitation of Liability level: 1 text: Neither party shall be liable for indirect or consequential damages. '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/templates/{templateId}/runs: post: tags: - Drafting summary: Generate a draft from a template description: 'Render a template into a new draft. Answers `202` with an operation. Poll it, then read the run to find the `draftId` it produced. Values you already know go in `slotOverrides` keyed by the variable''s `varId`; the extractor reads the rest out of `prompt` and never overwrites what you supplied.' operationId: templates.run 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`.' - name: templateId in: path required: true schema: type: string title: Templateid description: '`tpl_` identifier of one of your uploaded draft templates. Take it from `GET /v1/templates`.' - name: Idempotency-Key in: header required: false schema: anyOf: - type: string - type: 'null' title: Idempotency-Key description: A unique value of your choosing, so a retried launch returns the FIRST operation instead of starting a second billable job. Reusing one with a different body is refused. Retrying with the same key and the same body is free and is the intended way to recover from a timeout. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TemplateRunRequest' example: prompt: Two-year mutual NDA with Acme Corporation, governed by California law. slotOverrides: party_a_name: value responses: '202': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Operation' example: id: op_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 type: matrix.run status: succeeded createdAt: '2026-08-19T14:32:10Z' completedAt: '2026-08-19T14:32:10Z' matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 resource: kind: matrix id: mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 url: https://storage.vaquill.ai/exports/msa-acme-v3-redline.docx?signature=... progress: done: 24 total: 128 unit: cells requestId: req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) /v1/matters/{matterId}/template-runs/{runId}: get: tags: - Drafting summary: Get a template run description: 'One template run: what it was asked to fill in, and what it produced. Every slot carries where its value came from. A `source` of `user` was handed over by you; anything else was inferred by a model and is worth checking before the draft goes out. `draftId` is null until the run has finished rendering.' operationId: templateRuns.get 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`.' - name: runId in: path required: true schema: type: string title: Runid description: '`wfr_` identifier of one workflow RUN. Returned on the operation that launched it, and distinct from the `workflowId` that was run.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TemplateRun' example: id: dtr_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 templateId: tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 status: succeeded draftId: drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 prompt: Two-year mutual NDA with Acme Corporation, governed by California law. slots: - id: party_a_name value: value source: generated createdAt: '2026-08-19T14:32:10Z' completedAt: '2026-08-19T14:32:10Z' '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' '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' '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' servers: - url: https://api.vaquill.ai/workspace description: Vaquill Legal Workspace API (production) - url: /workspace description: Vaquill Legal Workspace API (relative to the mount) components: schemas: DraftExportRequest: properties: format: type: string enum: - docx - pdf title: Format description: 'Which format to render: `docx` or `pdf`.' examples: - docx additionalProperties: false type: object required: - format title: DraftExportRequest description: Ask for the draft rendered to a file. DraftImproveRequest: properties: instructions: anyOf: - type: string maxLength: 40000 - type: 'null' title: Instructions description: 'What to fix, in your own words. Optional: the pipeline runs its own analysis first and an instruction only steers it.' examples: - House paper. Cap liability at 12 months of fees; never accept uncapped indemnity. category: anyOf: - type: string maxLength: 64 minLength: 1 - type: 'null' title: Category description: Override the category. Defaults to the source draft's own, so supply this only when the source was misclassified. A source whose category we no longer draft falls back to `custom` rather than refusing the revision. examples: - commercial tone: type: string enum: - protective - balanced - permissive title: Tone description: How protective the revised language should be. default: balanced examples: - protective additionalProperties: false type: object title: DraftImproveRequest description: 'Revise an existing draft into a NEW one. The improvement never overwrites its source. That is the internal pipeline''s behaviour and it is the right one to publish: the run takes minutes and costs money, and a customer that dislikes the result still has the draft it started from.' TemplateRunRequest: properties: prompt: anyOf: - type: string maxLength: 8000 - type: 'null' title: Prompt description: 'Free text the extractor reads variable values out of. Optional: a template whose every variable is supplied in `slotOverrides` needs no prose.' examples: - Two-year mutual NDA with Acme Corporation, governed by California law. slotOverrides: additionalProperties: type: string maxLength: 4000 minLength: 1 type: object title: Slotoverrides description: Values you already know, keyed by the variable's `varId`. Recorded with source `user`, and the extractor never overwrites them. additionalProperties: false type: object title: TemplateRunRequest description: 'What to fill the template with. Context documents are deliberately absent in v1. The internal flow can take document ids as extra evidence for the extractor, and the same route will accept them additively; publishing them now would mean publishing an id space and an ownership check for a feature nobody has asked this API for. Generation from a prompt alone is supported by the pipeline as it stands.' TemplateFromDocumentRequest: properties: documentId: type: string title: Documentid description: '`doc_` identifier of a document in this organization to build the template from.' examples: - doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: anyOf: - type: string maxLength: 300 minLength: 1 - type: 'null' title: Title description: Display name. Defaults to the document's filename. examples: - Master Services Agreement description: anyOf: - type: string maxLength: 2000 - type: 'null' title: Description description: What this template is for, in your own words. examples: - Master services agreement with Acme for the 2026 platform rollout. category: anyOf: - type: string maxLength: 100 minLength: 1 - type: 'null' title: Category description: How you classify this template. Defaults to `custom`. examples: - commercial additionalProperties: false type: object required: - documentId title: TemplateFromDocumentRequest description: 'Turn a document you already uploaded into a template. Takes a `documentId` rather than a file. Bytes reach this API exactly one way, through `uploads.initiate` and the presigned part PUTs, so there is one media allowlist, one size ceiling and one answer to encryption at rest. The cost is stated: importing a template is four calls rather than one, and the source file stays as a document you own, can list, can download and can delete, which is how "which contract did this come from" is answerable months later. **A DOCX-sourced template keeps its Word structure; a later `templates.update` does not.** Replacing the body through this API replaces it with what markdown can express, so duplicate first if the original formatting matters.' Page_Template_: properties: data: items: $ref: '#/components/schemas/Template' type: array title: Data description: The rows in this window, in the collection's default order. pagination: $ref: '#/components/schemas/Pagination' description: Where this window sits in the full result set. additionalProperties: false type: object required: - data - pagination title: Page[Template] DraftReplaceRequest: properties: contentMarkdown: type: string maxLength: 500000 minLength: 1 title: Contentmarkdown description: 'The COMPLETE new body as markdown. This replaces the whole document: a partial body is not something this format can express, so sending one paragraph loses the rest. Whitespace alone is refused.' examples: - '# Mutual Non-Disclosure Agreement ## 1. Confidential Information Each party may disclose information that is confidential and proprietary to the other party. ' title: anyOf: - type: string maxLength: 200 minLength: 1 - type: 'null' title: Title description: New title. Omit to leave the title alone. examples: - Master Services Agreement status: anyOf: - type: string enum: - draft - review - final - archived - type: 'null' title: Status description: 'New document lifecycle status: `draft`, `review`, `final` or `archived`. Omit to leave it alone.' examples: - draft changeSummary: anyOf: - type: string maxLength: 500 - type: 'null' title: Changesummary description: Why this change was made. Recorded on the version snapshot the replace creates, so it shows up in the version list later. examples: - Tightened the indemnity carve-outs after counsel review. expectedVersion: anyOf: - type: integer minimum: 1.0 - type: 'null' title: Expectedversion description: The `version` you read before editing. Supply it so a concurrent write is refused rather than silently overwritten. Omitting it means 'overwrite whatever is there'. examples: - 1 additionalProperties: false type: object required: - contentMarkdown title: DraftReplaceRequest description: 'Replace a draft''s body, and optionally its title and lifecycle status. A PUT rather than a PATCH because `contentMarkdown` is the whole body: a partial body is not a thing this format can express, and pretending otherwise would invite a caller to send one paragraph and lose the rest. Title and status are left alone when omitted, which is what makes a body-only edit possible without restating metadata the caller did not read. `expectedVersion` is how a headless read-modify-write avoids a lost update. Omitting it means "overwrite whatever is there", which is a legitimate thing to want and a bad default to impose.' 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 Draft: properties: id: type: string title: Id description: Public identifier, `drf_` followed by 32 hex characters. examples: - drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: anyOf: - type: string - type: 'null' title: Matterid description: '`mat_` identifier of the matter this draft belongs to, when it belongs to one.' examples: - mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: type: string title: Title description: The draft's title. examples: - Master Services Agreement category: type: string title: Category description: What kind of document this is, as a category slug. examples: - commercial practiceArea: type: string title: Practicearea description: Practice area the draft sits in. examples: - commercial status: type: string title: Status description: 'Where the DOCUMENT is in its own lifecycle: `draft`, `review`, `final` or `archived`. Set by you. This is not the same as `generationStatus`.' examples: - draft source: type: string title: Source description: 'How the draft came to exist: `generated` by the pipeline, `uploaded` from a file, `imported` from editor content, or `analysis` where an analysis produced it.' examples: - generated version: type: integer title: Version description: Current version number, counting from 1. Pass it as `expectedVersion` on a replace to avoid a lost update. examples: - 3 generationStatus: $ref: '#/components/schemas/OperationStatus' description: Where the JOB that produced this draft got to, in the five public statuses. Set only by the pipeline. A draft the pipeline never touched reads `succeeded`. examples: - succeeded governingLawState: anyOf: - type: string - type: 'null' title: Governinglawstate description: The governing law pinned on the draft, for example `ca` or `federal`. examples: - ca createdAt: type: string format: date-time title: Createdat description: When the draft was created (RFC 3339). examples: - '2026-08-19T14:32:10Z' updatedAt: type: string format: date-time title: Updatedat description: When the draft was last modified (RFC 3339). examples: - '2026-08-19T14:32:10Z' sections: items: $ref: '#/components/schemas/DraftSection' type: array title: Sections description: The draft body, section by section. Send edits back as `contentMarkdown`; request bytes from the export route. additionalProperties: false type: object required: - id - title - category - practiceArea - status - source - version - generationStatus - createdAt - updatedAt - sections title: Draft description: One draft with its body, section by section. TemplateUpdateRequest: properties: contentMarkdown: type: string maxLength: 500000 minLength: 1 title: Contentmarkdown description: 'The COMPLETE new body as markdown. This replaces the whole template: a partial body is not something this format can express. Whitespace alone is refused.' examples: - '# Mutual Non-Disclosure Agreement ## 1. Confidential Information Each party may disclose information that is confidential and proprietary to the other party. ' title: anyOf: - type: string maxLength: 300 minLength: 1 - type: 'null' title: Title description: New display name. Omit to leave it alone. examples: - Mutual NDA description: anyOf: - type: string maxLength: 2000 - type: 'null' title: Description description: New description. Omit to leave it alone. examples: - Master services agreement with Acme for the 2026 platform rollout. additionalProperties: false type: object required: - contentMarkdown title: TemplateUpdateRequest description: 'Replace a template''s body, and optionally its title and description. A PUT rather than a PATCH, matching `drafts.update`: `contentMarkdown` is the WHOLE body, so sending one clause replaces the template with that clause. Title and description are left alone when omitted. Variables are re-detected from the new body and the frozen-text hash is recomputed in the same write. That hash is the renderer''s integrity baseline over the non-variable segments, so leaving it stale would check the next run against the body the template used to have. **This is lossy against a DOCX-imported template.** The rich converter preserves Word formatting that markdown cannot express, and replacing the body through here discards it. Duplicate the template first if you want to keep the original.' OperationProgress: properties: done: type: integer minimum: 0.0 title: Done description: How many units are finished. examples: - 24 total: type: integer minimum: 0.0 title: Total description: How many units there are in total. Can legitimately be zero for an empty run. examples: - 128 unit: type: string enum: - cells - steps - documents - files - rows - percent title: Unit description: 'What `done` and `total` are counting. Always read it: a workflow run counts `percent` while a matrix run counts `cells`, so `{done: 43, total: 100}` alone is ambiguous.' examples: - cells additionalProperties: false type: object required: - done - total - unit title: OperationProgress description: 'How far along, and in what units. The unit is not decoration. A workflow run stores only a percentage while a matrix run stores cell counts, so `{done: 43, total: 100}` with no unit reads as 43 of 100 documents and a client builds a wrong estimate from it.' OperationResource: properties: kind: type: string title: Kind description: What sort of thing was produced, for example `matrix` or `document`. examples: - matrix id: type: string title: Id description: Public identifier of the produced resource, carrying its own type prefix, for example `mtx_` for a matrix. examples: - mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 url: anyOf: - type: string - type: 'null' title: Url description: Path on this API where the resource can be read, RELATIVE to the API root and never absolute. Absent when the resource has no addressable path, which happens for work started outside a matter. Absent means the id is real and there is nowhere to GET it; it is not an error. examples: - https://storage.vaquill.ai/exports/msa-acme-v3-redline.docx?signature=... additionalProperties: false type: object required: - kind - id title: OperationResource description: 'What the operation produced, or is producing. `url` is a path on this API rather than an absolute URL, because the service is mounted today and gets its own hostname later (docs 07.5). A relative path survives that move; a baked-in host does not.' TemplateVariable: properties: id: type: string title: Id description: The variable's `varId`, and the key to use in `slotOverrides` when you run this template. Stable across every run. examples: - party_a_name name: type: string title: Name description: The detected or authored name for this variable. examples: - Counterparty name label: anyOf: - type: string - type: 'null' title: Label description: Display label, when one was set. Falls back to `name`. examples: - Counterparty name kind: type: string title: Kind description: 'What sort of value belongs here: `party`, `date`, `money`, `jurisdiction`, `address`, `number`, `duration`, `text`, `other`. Drives how the extractor is constrained when it fills the slot.' examples: - party hint: anyOf: - type: string - type: 'null' title: Hint description: Guidance the extractor was given for this variable. examples: - The counterparty's full legal entity name, as it appears on the signature block. defaultValue: anyOf: - type: string - type: 'null' title: Defaultvalue description: Value used when nothing is supplied or extracted. examples: - Acme Corporation position: type: integer title: Position description: Where this variable sits in the template body, counting from zero. examples: - 0 additionalProperties: false type: object required: - id - name - kind - position title: TemplateVariable description: 'One fillable span the template declares. Published because `slotOverrides` on a run is keyed by `id` and **nothing else on this surface publishes one**. Before this model existed, the only way to learn a template''s keys was to run it once and read the slots back off the finished run, which is a paid LLM call to discover a schema.' DraftCopyRequest: properties: title: anyOf: - type: string maxLength: 200 minLength: 1 - type: 'null' title: Title description: Title for the copy. Defaults to the source title followed by " (copy)". examples: - Master Services Agreement additionalProperties: false type: object title: DraftCopyRequest description: 'Copy a draft, optionally under a new name. Send `{}` to accept the defaults. The copy starts at version 1 with no history of its own and status `draft`, and it lands in the same matter: it is a new document that happens to start from this one, not a branch of it.' DraftCategory: properties: id: type: string title: Id description: The category slug. Send it as `category` on a draft generation. examples: - nda label: type: string title: Label description: The product's own name for this document type, taken from the format the generator uses rather than from a second list, so it cannot drift from what gets written. examples: - Liability cap practiceArea: type: string title: Practicearea description: The practice area a draft in this category is filed under. Every category reads `general` today, because that is the only practice area the product registers. examples: - commercial additionalProperties: false type: object required: - id - label - practiceArea title: DraftCategory description: One document type the drafting pipeline knows how to write. DraftFromDocumentRequest: properties: documentId: type: string title: Documentid description: '`doc_` identifier of a document in this matter to convert into a draft.' examples: - doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: anyOf: - type: string maxLength: 200 minLength: 1 - type: 'null' title: Title description: Title for the draft. Defaults to the document's filename. examples: - Master Services Agreement category: type: string maxLength: 64 minLength: 1 title: Category description: What kind of document this is, as a category slug from `draftCategories.list`. Defaults to `custom`, which is always accepted. default: custom examples: - commercial additionalProperties: false type: object required: - documentId title: DraftFromDocumentRequest description: 'Turn a document you already uploaded into an editable draft. Takes a `documentId` rather than a file, for the reason every other file on this surface does: bytes reach this API through `uploads.initiate` and the presigned part PUTs, so there is one media allowlist, one size ceiling and one answer to encryption at rest. The ORIGINAL file is what gets converted, not the text the ingest pipeline extracted for retrieval. That text is chunk-shaped and has already lost the headings a contract is navigated by. No AI runs. This is a format conversion, so it answers `201` with the draft rather than `202` with an operation.' DraftCreateRequest: properties: category: type: string maxLength: 64 minLength: 1 title: Category description: What kind of document to generate, as a category slug. Validated against the live vocabulary when the generation starts. examples: - commercial title: type: string maxLength: 200 minLength: 1 title: Title description: Title for the generated draft. examples: - Master Services Agreement governingLawState: type: string maxLength: 80 minLength: 1 title: Governinglawstate description: 'Governing law to pin. Accepts a code (`ca`), a name (`California`) or the sentinel `federal`. Required: a US draft with no pinned governing law cites nothing.' examples: - ca tone: type: string enum: - protective - balanced - permissive title: Tone description: 'How protective the generated language should be: `protective`, `balanced` or `permissive`.' default: balanced examples: - protective specialInstructions: anyOf: - type: string maxLength: 40000 - type: 'null' title: Specialinstructions description: Anything specific this draft needs, in your own words. examples: - Two-year term, mutual, governed by California law. variables: additionalProperties: type: string type: object title: Variables description: 'Template variable values, for example `{"party_a_name": "Acme Corp"}`. Which keys mean anything is a property of the category, so this is deliberately free-form. Unfilled placeholders are counted on export.' practiceArea: anyOf: - type: string maxLength: 64 minLength: 1 - type: 'null' title: Practicearea description: Practice area for the draft. Inferred from the category when omitted. examples: - commercial additionalProperties: false type: object required: - category - title - governingLawState title: DraftCreateRequest description: 'Start a generation. There is no synchronous create. `jurisdiction` is deliberately absent and fixed at US: this is a US-only product (OPINIONS.md), and a field whose only accepted value is the default is a field a customer has to discover before they can ignore it. `governingLawState` is required for the same reason it is required internally: a US draft with no pinned governing law cites nothing.' DraftVersion: properties: version: type: integer title: Version description: The version number this entry records. examples: - 3 changeSummary: anyOf: - type: string - type: 'null' title: Changesummary description: Why this version was created, when a summary was supplied. examples: - Tightened the indemnity carve-outs after counsel review. createdAt: type: string format: date-time title: Createdat description: When this version was snapshotted (RFC 3339). examples: - '2026-08-19T14:32:10Z' additionalProperties: false type: object required: - version - createdAt title: DraftVersion description: 'One point in a draft''s history. Metadata only. The stored CONTENT of an old version is not published. A version body would be a second representation of the same document with the same TipTap problem and no customer has asked to read one; `changeSummary` plus the version number is what makes the list useful for an audit trail.' TemplateCopyRequest: properties: title: anyOf: - type: string maxLength: 300 minLength: 1 - type: 'null' title: Title description: New display name. Defaults to the source title followed by " (copy)". examples: - Master Services Agreement additionalProperties: false type: object title: TemplateCopyRequest description: 'Copy a template, optionally under a new name. Send `{}` to accept the defaults. A copy is a real second template with its own id and its own variable rows, so editing it cannot touch the original, which is what makes it the safe move before a lossy body replacement.' Operation: properties: id: type: string title: Id description: Public identifier, `op_` followed by 32 hex characters. Poll `GET /v1/operations/{operationId}` with it. examples: - op_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 type: type: string title: Type description: What kind of work this is, for example `matrix.run` or `draft.generate`. examples: - matrix.run status: $ref: '#/components/schemas/OperationStatus' description: 'One of five values: `queued`, `running`, `succeeded`, `failed`, `cancelled`. There is no sixth and there are no synonyms. Stop polling once it is `succeeded`, `failed` or `cancelled`.' examples: - succeeded createdAt: type: string format: date-time title: Createdat description: When the operation was accepted (RFC 3339). examples: - '2026-08-19T14:32:10Z' completedAt: anyOf: - type: string format: date-time - type: 'null' title: Completedat description: When the operation reached a terminal status (RFC 3339). Present if and only if the status is terminal. examples: - '2026-08-19T14:32:10Z' matterId: anyOf: - type: string - type: 'null' title: Matterid description: '`mat_` identifier of the matter this work belongs to, when it belongs to one.' examples: - mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 resource: anyOf: - $ref: '#/components/schemas/OperationResource' - type: 'null' description: What the operation produced. Absent until the underlying job row exists, which an idempotent replay can briefly observe, so treat absence as 'not yet' rather than 'never'. error: anyOf: - $ref: '#/components/schemas/OperationError' - type: 'null' description: Why the work failed. Present only when `status` is `failed`. Partial success is `succeeded` with `progress.done < progress.total`, never an error. progress: anyOf: - $ref: '#/components/schemas/OperationProgress' - type: 'null' description: How far along the work is, when the underlying job reports it. Absent does not mean no progress. requestId: anyOf: - type: string - type: 'null' title: Requestid description: The `X-Request-ID` of the request that created this operation. Quote it in a support ticket. examples: - req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 additionalProperties: false type: object required: - id - type - status - createdAt title: Operation description: 'One long-running operation, whatever kind of work it is. Readable for `OPERATION_RETENTION_DAYS` after creation, per AIP-151.' 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 TemplateCreateRequest: properties: title: type: string maxLength: 300 minLength: 1 title: Title description: Display name for the template. examples: - Mutual NDA contentMarkdown: type: string maxLength: 500000 minLength: 1 title: Contentmarkdown description: 'The template body as markdown, placeholders included. Whitespace alone is refused: the converter answers it with a valid EMPTY document, which would be a template that renders a blank page.' examples: - '# Mutual Non-Disclosure Agreement ## 1. Confidential Information Each party may disclose information that is confidential and proprietary to the other party. ' description: anyOf: - type: string maxLength: 2000 - type: 'null' title: Description description: What this template is for, in your own words. examples: - Master services agreement with Acme for the 2026 platform rollout. category: anyOf: - type: string maxLength: 100 minLength: 1 - type: 'null' title: Category description: How you classify this template. Defaults to `custom`; free-form, not a drafting category. examples: - commercial additionalProperties: false type: object required: - title - contentMarkdown title: TemplateCreateRequest description: 'Author a template from markdown you supply. **Variables are detected for you, on this call, and the response carries what was found.** A placeholder written as `[COUNTERPARTY NAME]`, `{{party_a}}` or a run of underscores survives the markdown round trip as literal characters, and the detector re-derives the mark from it, so a template authored here cannot land in the state where it runs and interpolates nothing. Detection is regex over the flattened text: deterministic, free and sub-millisecond. The product also has an LLM refinement pass and this API does not run it, so a template imported here may detect fewer variables than the same file imported in the browser. It refines display NAMES and adds spans the regex missed; the identifiers `slotOverrides` is keyed by are deliberately left alone by it either way.' Page_DraftSummary_: properties: data: items: $ref: '#/components/schemas/DraftSummary' type: array title: Data description: The rows in this window, in the collection's default order. pagination: $ref: '#/components/schemas/Pagination' description: Where this window sits in the full result set. additionalProperties: false type: object required: - data - pagination title: Page[DraftSummary] DraftSummary: properties: id: type: string title: Id description: Public identifier, `drf_` followed by 32 hex characters. examples: - drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: anyOf: - type: string - type: 'null' title: Matterid description: '`mat_` identifier of the matter this draft belongs to, when it belongs to one.' examples: - mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: type: string title: Title description: The draft's title. examples: - Master Services Agreement category: type: string title: Category description: What kind of document this is, as a category slug. examples: - commercial practiceArea: type: string title: Practicearea description: Practice area the draft sits in. examples: - commercial status: type: string title: Status description: 'Where the DOCUMENT is in its own lifecycle: `draft`, `review`, `final` or `archived`. Set by you. This is not the same as `generationStatus`.' examples: - draft source: type: string title: Source description: 'How the draft came to exist: `generated` by the pipeline, `uploaded` from a file, `imported` from editor content, or `analysis` where an analysis produced it.' examples: - generated version: type: integer title: Version description: Current version number, counting from 1. Pass it as `expectedVersion` on a replace to avoid a lost update. examples: - 3 generationStatus: $ref: '#/components/schemas/OperationStatus' description: Where the JOB that produced this draft got to, in the five public statuses. Set only by the pipeline. A draft the pipeline never touched reads `succeeded`. examples: - succeeded governingLawState: anyOf: - type: string - type: 'null' title: Governinglawstate description: The governing law pinned on the draft, for example `ca` or `federal`. examples: - ca createdAt: type: string format: date-time title: Createdat description: When the draft was created (RFC 3339). examples: - '2026-08-19T14:32:10Z' updatedAt: type: string format: date-time title: Updatedat description: When the draft was last modified (RFC 3339). examples: - '2026-08-19T14:32:10Z' additionalProperties: false type: object required: - id - title - category - practiceArea - status - source - version - generationStatus - createdAt - updatedAt title: DraftSummary description: 'A draft as it appears in a list: everything except the body.' 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.' TemplateRun: properties: id: type: string title: Id description: Public identifier of this run, `dtr_` followed by 32 hex characters. examples: - dtr_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 templateId: type: string title: Templateid description: '`tpl_` identifier of the template that was run.' examples: - tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 matterId: anyOf: - type: string - type: 'null' title: Matterid description: '`mat_` identifier of the matter the run belongs to, when it belongs to one.' examples: - mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 status: $ref: '#/components/schemas/OperationStatus' description: Run status, using the same five public values as an operation. The internal stages `planning` and `extracting` both read as `running`. examples: - succeeded draftId: anyOf: - type: string - type: 'null' title: Draftid description: '`drf_` identifier of the draft the run produced. Null until the run has finished rendering one.' examples: - drf_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 prompt: anyOf: - type: string - type: 'null' title: Prompt description: The prompt this run was started with, echoed back. examples: - Two-year mutual NDA with Acme Corporation, governed by California law. slots: items: $ref: '#/components/schemas/TemplateSlot' type: array title: Slots description: Every template variable and the value the run put in it, including where each value came from. createdAt: type: string format: date-time title: Createdat description: When the run started (RFC 3339). examples: - '2026-08-19T14:32:10Z' completedAt: anyOf: - type: string format: date-time - type: 'null' title: Completedat description: When the run reached a terminal status (RFC 3339). examples: - '2026-08-19T14:32:10Z' additionalProperties: false type: object required: - id - templateId - status - slots - createdAt title: TemplateRun description: One invocation, and what it produced. Page_DraftVersion_: properties: data: items: $ref: '#/components/schemas/DraftVersion' type: array title: Data description: The rows in this window, in the collection's default order. pagination: $ref: '#/components/schemas/Pagination' description: Where this window sits in the full result set. additionalProperties: false type: object required: - data - pagination title: Page[DraftVersion] Page_DraftCategory_: properties: data: items: $ref: '#/components/schemas/DraftCategory' type: array title: Data description: The rows in this window, in the collection's default order. pagination: $ref: '#/components/schemas/Pagination' description: Where this window sits in the full result set. additionalProperties: false type: object required: - data - pagination title: Page[DraftCategory] TemplateDetail: properties: id: type: string title: Id description: Public identifier, `tpl_` followed by 32 hex characters. Name it when starting a run. examples: - tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: type: string title: Title description: The template's display name. examples: - Master Services Agreement description: anyOf: - type: string - type: 'null' title: Description description: Free-text description of what the template is for. examples: - Master services agreement with Acme for the 2026 platform rollout. category: type: string title: Category description: The template's category, as the customer classified it on upload. examples: - commercial sourceFilename: anyOf: - type: string - type: 'null' title: Sourcefilename description: Filename of the document this template was created from. Published because it is how a person recognizes which template a run used, months later. examples: - msa-acme-v3.docx createdAt: type: string format: date-time title: Createdat description: When the template was created (RFC 3339). examples: - '2026-08-19T14:32:10Z' updatedAt: type: string format: date-time title: Updatedat description: When the template was last modified (RFC 3339). examples: - '2026-08-19T14:32:10Z' variables: items: $ref: '#/components/schemas/TemplateVariable' type: array title: Variables description: Every fillable span, in document order. The `id` of each is what `slotOverrides` on a run is keyed by. sections: items: $ref: '#/components/schemas/DraftSection' type: array title: Sections description: The template body, section by section, with the placeholder text left in place. Send a replacement as `contentMarkdown`. additionalProperties: false type: object required: - id - title - category - createdAt - updatedAt - variables - sections title: TemplateDetail description: 'One template with everything needed to run it without guessing. `variables` is the reason this model exists at all, and `sections` is here for the same reason a draft publishes them: a caller deciding WHICH template to run needs to read what it says, and the editor''s own document model does not cross this boundary in either direction.' Pagination: properties: limit: type: integer title: Limit description: The `limit` that was applied to this request. examples: - 50 offset: type: integer title: Offset description: The `offset` that was applied to this request. examples: - 0 total: type: integer title: Total description: Total rows matching the filter, not the number returned in `data`. Use it to size a job before running it. examples: - 128 hasMore: type: boolean title: Hasmore description: True when rows remain beyond this window. Derived from `offset + len(data) < total`, so a full final page correctly reports `false` rather than sending you after an empty page. examples: - false additionalProperties: false type: object required: - limit - offset - total - hasMore title: Pagination description: 'Where the caller is, and whether there is more. `total` is the count of rows matching the filter, not the count returned, so a caller can size a job before running it.' Template: properties: id: type: string title: Id description: Public identifier, `tpl_` followed by 32 hex characters. Name it when starting a run. examples: - tpl_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6 title: type: string title: Title description: The template's display name. examples: - Mutual NDA description: anyOf: - type: string - type: 'null' title: Description description: Free-text description of what the template is for. examples: - Master services agreement with Acme for the 2026 platform rollout. category: type: string title: Category description: The template's category, as the customer classified it on upload. examples: - commercial sourceFilename: anyOf: - type: string - type: 'null' title: Sourcefilename description: Filename of the document this template was created from. Published because it is how a person recognizes which template a run used, months later. examples: - msa-acme-v3.docx createdAt: type: string format: date-time title: Createdat description: When the template was created (RFC 3339). examples: - '2026-08-19T14:32:10Z' updatedAt: type: string format: date-time title: Updatedat description: When the template was last modified (RFC 3339). examples: - '2026-08-19T14:32:10Z' additionalProperties: false type: object required: - id - title - category - createdAt - updatedAt title: Template description: 'One uploaded template, as listed. The TipTap body and the variable definitions are not published. The body is the same editor document a draft carries, and the variable list is only meaningful against it; what a headless caller needs is which template to name and what came back after it ran.' OperationError: properties: code: type: string title: Code description: Stable, machine-readable failure code. Branch on this, never on `message`. examples: - EXTRACTION_FAILED message: type: string title: Message description: Human-readable explanation, sanitized of internal paths and stack frames. Wording may change; do not parse it. examples: - The upstream extraction did not finish. additionalProperties: false type: object required: - code - message title: OperationError description: 'Why a failed operation failed, in terms a customer can act on. `code` is stable and machine-readable. `message` is sanitized: the internal job tables store stack traces and file paths in their `error_message` columns, and forwarding those verbatim leaks our internals into a customer''s logs.' DraftSection: properties: heading: anyOf: - type: string - type: 'null' title: Heading description: The section's heading. Null for body text preceding the first heading, which is where a parties block or preamble lives. examples: - 8. Limitation of Liability level: anyOf: - type: integer - type: 'null' title: Level description: Heading depth, 1 to 6. Null when there is no heading. examples: - 1 text: type: string title: Text description: The text beneath this heading, as plain text. examples: - Neither party shall be liable for indirect or consequential damages. additionalProperties: false type: object required: - text title: DraftSection description: 'One heading and the text beneath it. `heading` is null for body text that precedes the first heading, which is where a parties block or a preamble lives. Dropping it because it has no heading would lose the first paragraph of most contracts.' TemplateSlot: properties: id: type: string title: Id description: The variable's `varId` on the template, stable across every run of that template. examples: - party_a_name value: anyOf: - type: string - type: 'null' title: Value description: What the run put in this slot. Null when nothing was supplied or extracted for it. examples: - Acme Corporation source: anyOf: - type: string - type: 'null' title: Source description: 'Where the value came from: `prompt`, `context`, `computed`, `user` or `default`. Read it before relying on a value: `user` was handed over, the rest were inferred by a model.' examples: - prompt additionalProperties: false type: object required: - id title: TemplateSlot description: One variable and the value the run put in it. DraftExport: properties: format: type: string enum: - docx - pdf title: Format description: The format that was rendered. examples: - docx filename: type: string title: Filename description: Suggested filename for the rendered file. examples: - msa-acme-v3.docx sizeBytes: type: integer title: Sizebytes description: Length of the DECODED file in bytes, so you can size storage without doing base64 arithmetic. examples: - 248193 content: type: string title: Content description: 'The rendered file, base64 encoded. Bytes rather than a signed URL because a draft is rendered on demand: a URL would mean writing your work product to storage first.' examples: - UEsDBBQABgAIAAAAIQ... unfilledPlaceholders: type: integer title: Unfilledplaceholders description: 'How many `[Party Name]`-style placeholders are still unfilled. Check it before filing an export unread: a non-zero value means the document is not finished.' examples: - 0 additionalProperties: false type: object required: - format - filename - sizeBytes - content - unfilledPlaceholders title: DraftExport description: 'A rendered draft, returned as bytes rather than as a URL. Every other artifact on this API is a signed URL over an object a worker already wrote. A draft export is rendered on demand, so a URL would mean writing client work product to storage first, and with encryption on in every deployment that is a choice between a URL the customer cannot decrypt and plaintext in a bucket. `content` is base64 and bounded by `MAX_INLINE_EXPORT_BYTES`; docs 10-DRAFT_BODY.md records the trade.' 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.' externalDocs: description: Getting started guide and error reference url: https://vaquill.ai/docs/workspace-api x-refined-from: - vaquill-ai-workspace-openapi.json - vaquill-ai-workspace-openapi.yml