curl --request POST \
--url https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Vendor agreement review"
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices"
payload = { "title": "Vendor agreement review" }
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({title: 'Vendor agreement review'})
};
fetch('https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices', 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"
payload := strings.NewReader("{\n \"title\": \"Vendor agreement review\"\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"
}Create a matrix
Build a grid. Nothing is extracted until you run it.
Rows are documents and columns are questions, so the grid is documents x columns cells and each cell is one billable extraction when the matrix is
run. Every document must already be in this matter and finished ingesting:
a still-ingesting document is refused, because retrieval over it would
answer “not in this document” for every column.
Note the column vocabulary: free_text, single_select, date, money,
yes_no, party_name. There is no text, number or boolean.
curl --request POST \
--url https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Vendor agreement review"
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices"
payload = { "title": "Vendor agreement review" }
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({title: 'Vendor agreement review'})
};
fetch('https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices', 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"
payload := strings.NewReader("{\n \"title\": \"Vendor agreement review\"\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.
Body
Build a grid. Nothing is extracted until matrices.run.
Display title for the matrix.
1 - 300"Vendor agreement review"
Free-text description of what the matrix is for.
2000"Master services agreement with Acme for the 2026 platform rollout."
doc_ identifiers that become the rows, one row per document. Each must be in this matter and must have finished ingesting. Duplicates are refused rather than de-duplicated.
["value"]
The questions asked of every document, one column each. At most 60. Documents times columns is the number of billable extractions a run performs.
60Show 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?

