curl --request POST \
--url https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"columns": [
{
"label": "Liability cap",
"question": "What is the liability cap, and what does it apply to?",
"columnType": "free_text",
"options": [
"yes",
"no",
"not addressed"
],
"instructions": "House paper. Cap liability at 12 months of fees; never accept uncapped indemnity."
}
]
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns"
payload = { "columns": [
{
"label": "Liability cap",
"question": "What is the liability cap, and what does it apply to?",
"columnType": "free_text",
"options": ["yes", "no", "not addressed"],
"instructions": "House paper. Cap liability at 12 months of fees; never accept uncapped indemnity."
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
columns: [
{
label: 'Liability cap',
question: 'What is the liability cap, and what does it apply to?',
columnType: 'free_text',
options: ['yes', 'no', 'not addressed'],
instructions: 'House paper. Cap liability at 12 months of fees; never accept uncapped indemnity.'
}
]
})
};
fetch('https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns"
payload := strings.NewReader("{\n \"columns\": [\n {\n \"label\": \"Liability cap\",\n \"question\": \"What is the liability cap, and what does it apply to?\",\n \"columnType\": \"free_text\",\n \"options\": [\n \"yes\",\n \"no\",\n \"not addressed\"\n ],\n \"instructions\": \"House paper. Cap liability at 12 months of fees; never accept uncapped indemnity.\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"matterId": "mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"title": "Vendor agreement review",
"description": "Master services agreement with Acme for the 2026 platform rollout.",
"status": "succeeded",
"columns": [
{
"id": "col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"label": "Liability cap",
"question": "What is the liability cap, and what does it apply to?",
"columnType": "free_text",
"options": [
"yes",
"no",
"not addressed"
],
"instructions": "House paper. Cap liability at 12 months of fees; never accept uncapped indemnity.",
"dependsOnColumnId": "col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"gateExpression": "yes",
"injectUpstream": false,
"position": 0
}
],
"rows": [
{
"id": "row_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"documentId": "doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"filename": "msa-acme-v3.docx",
"position": 0
}
],
"cellCount": 24,
"pendingCellCount": 0,
"errorCellCount": 0,
"createdAt": "2026-08-19T14:32:10Z",
"updatedAt": "2026-08-19T14:32:10Z"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"errors": [
{
"location": "<string>",
"message": "<string>",
"type": "<string>"
}
],
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}Add questions as matrix columns
Add questions to the grid, one column each. Extracts nothing.
Every new column gets one pending cell per existing row, so adding one
column to a forty-row grid adds forty billable extractions to the next run.
The response carries the new pendingCellCount.
Conditional columns are set with PATCH .../columns/{columnId} once these
exist, because a dependency names a column id and these do not have one yet.
curl --request POST \
--url https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"columns": [
{
"label": "Liability cap",
"question": "What is the liability cap, and what does it apply to?",
"columnType": "free_text",
"options": [
"yes",
"no",
"not addressed"
],
"instructions": "House paper. Cap liability at 12 months of fees; never accept uncapped indemnity."
}
]
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns"
payload = { "columns": [
{
"label": "Liability cap",
"question": "What is the liability cap, and what does it apply to?",
"columnType": "free_text",
"options": ["yes", "no", "not addressed"],
"instructions": "House paper. Cap liability at 12 months of fees; never accept uncapped indemnity."
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
columns: [
{
label: 'Liability cap',
question: 'What is the liability cap, and what does it apply to?',
columnType: 'free_text',
options: ['yes', 'no', 'not addressed'],
instructions: 'House paper. Cap liability at 12 months of fees; never accept uncapped indemnity.'
}
]
})
};
fetch('https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/columns"
payload := strings.NewReader("{\n \"columns\": [\n {\n \"label\": \"Liability cap\",\n \"question\": \"What is the liability cap, and what does it apply to?\",\n \"columnType\": \"free_text\",\n \"options\": [\n \"yes\",\n \"no\",\n \"not addressed\"\n ],\n \"instructions\": \"House paper. Cap liability at 12 months of fees; never accept uncapped indemnity.\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"matterId": "mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"title": "Vendor agreement review",
"description": "Master services agreement with Acme for the 2026 platform rollout.",
"status": "succeeded",
"columns": [
{
"id": "col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"label": "Liability cap",
"question": "What is the liability cap, and what does it apply to?",
"columnType": "free_text",
"options": [
"yes",
"no",
"not addressed"
],
"instructions": "House paper. Cap liability at 12 months of fees; never accept uncapped indemnity.",
"dependsOnColumnId": "col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"gateExpression": "yes",
"injectUpstream": false,
"position": 0
}
],
"rows": [
{
"id": "row_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"documentId": "doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"filename": "msa-acme-v3.docx",
"position": 0
}
],
"cellCount": 24,
"pendingCellCount": 0,
"errorCellCount": 0,
"createdAt": "2026-08-19T14:32:10Z",
"updatedAt": "2026-08-19T14:32:10Z"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"errors": [
{
"location": "<string>",
"message": "<string>",
"type": "<string>"
}
],
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}{
"type": "https://vaquill.ai/docs/workspace-api/errors/insufficient-scope",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential carries matters:read. This operation needs matters:write.",
"instance": "/workspace/v1/matters/mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"requestId": "req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
}Authorizations
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.
Path Parameters
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.
mtx_ identifier of the matrix. Take it from the matter's matrix list.
Body
Questions to add to the grid, one column each.
Every added column backfills a pending cell against every existing row, so
adding one column to a forty-row grid creates forty cells and moves
pendingCellCount by forty. That is why the response is the whole matrix
rather than the created columns: the number a caller needs before deciding
whether to run is the new cell count, and it is invisible in a response that
only describes what was created.
Conditional columns are not settable here. A dependency names a col_ id,
and the ids in this request do not exist yet; patch the edges with
matrices.updateColumn once the create has returned them.
The questions to add, one column each. At most 60 in one request, and at most 60 in the grid.
1 - 60 elementsShow child attributes
Show child attributes
Response
Successful Response
The grid header plus its axes. Cells are a separate, paged read.
Rows and columns are inlined because they are bounded and because a cell is unreadable without them: a cell names a row id and a column id and nothing else, so a client that could not resolve those would have to page the whole grid to interpret one answer.
Public identifier, mtx_ followed by 32 hex characters.
"mtx_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
mat_ identifier of the matter this matrix belongs to.
"mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
Display title for the matrix.
"Vendor agreement review"
Matrix status, using the same five public values as an operation.
queued, running, succeeded, failed, cancelled "succeeded"
When the matrix was created (RFC 3339).
"2026-08-19T14:32:10Z"
When the matrix was last updated (RFC 3339).
"2026-08-19T14:32:10Z"
Free-text description of what the matrix is for.
"Master services agreement with Acme for the 2026 platform rollout."
Every column, inlined. A cell names only ids, so these are what make one readable.
Show child attributes
Show child attributes
Every row, inlined, one per document.
Show child attributes
Show child attributes
Total cells in the grid, which is rows times columns.
24
Cells that have not produced an answer yet. Zero means extraction is complete.
0
Cells whose extraction failed. These are distinct from cells that succeeded with a null answer.
0
Was this page helpful?

