Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Vaquill Ai Operations API
version: 1.0.0
description: 'Operations tagged Operations 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: Operations
description: 'The one job envelope. Every long-running call answers `202` with an operation, and polling this resource is the only way to learn it finished: there are no webhooks. Five statuses, no synonyms.'
paths:
/v1/operations/{operationId}:
get:
tags:
- Operations
summary: Get a long-running operation
description: 'Read one operation.
404 covers "no such id", "not yours" and "past the 30-day window" alike, so
the status code cannot be used to probe for operations in another tenant.'
operationId: operations.get
parameters:
- name: operationId
in: path
required: true
schema:
type: string
title: Operationid
description: '`op_` identifier returned in the `202` body of whatever started the work. Poll this resource until `status` is terminal, honouring `Retry-After`; there are no webhooks.'
responses:
'200':
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/operations:
get:
tags:
- Operations
summary: List operations
description: 'Every operation this credential can see, newest first.
This is how you recover an operation id you did not keep, and how you find
what is still running. Filter with `status`, `type` and `matterId`.
A running operation''s status here can lag slightly behind the truth. Poll
`GET /v1/operations/{operationId}` for an authoritative answer; this route
is for finding which ones to poll.
Only operations whose capability your credential can read are returned. A
credential with no matching scope gets an empty page rather than an error.'
operationId: operations.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.'
- name: status
in: query
required: false
schema:
anyOf:
- $ref: '#/components/schemas/OperationStatus'
- type: 'null'
description: Return only operations in this status. One of the five public values. `queued` and `running` together are what is still in flight.
title: Status
description: Return only operations in this status. One of the five public values. `queued` and `running` together are what is still in flight.
- name: type
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Return only operations of this type, for example `review.run`. An unknown type returns an empty page rather than an error.
title: Type
description: Return only operations of this type, for example `review.run`. An unknown type returns an empty page rather than an error.
- name: matterId
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Return only operations belonging to this matter.
title: Matterid
description: Return only operations belonging to this matter.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/Page_Operation_'
example:
data:
- 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
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)
components:
schemas:
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.'
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.'
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.'
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
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.'
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.'
Page_Operation_:
properties:
data:
items:
$ref: '#/components/schemas/Operation'
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[Operation]
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
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