curl --request PATCH \
--url https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/cells/{cellId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"answer": "Twelve months of fees paid.",
"review": "approved"
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/cells/{cellId}"
payload = {
"answer": "Twelve months of fees paid.",
"review": "approved"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({answer: 'Twelve months of fees paid.', review: 'approved'})
};
fetch('https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/cells/{cellId}', 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}/cells/{cellId}"
payload := strings.NewReader("{\n \"answer\": \"Twelve months of fees paid.\",\n \"review\": \"approved\"\n}")
req, _ := http.NewRequest("PATCH", 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": "cel_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"rowId": "row_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"columnId": "col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"status": "succeeded",
"answer": "Twelve months of fees paid.",
"citations": [
{
"quote": "in no event shall either party be liable for indirect damages",
"page": 1,
"chunkId": "chunk_00f1"
}
],
"confidence": 0.92,
"extractedAt": "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"
}Write or review a matrix cell answer
Write a human answer into a cell, or record a review decision on it.
An answer written here survives the next run: a run with no body skips
cells that already carry a human answer or a review decision and does not
charge for them. {"force": true} on a run has no such guard and overwrites
them.
review is approved or rejected. The extractor’s own statuses cannot be
written: an integration writing extracted onto an answer no machine
produced makes the grid unauditable. Citations cannot be written either,
because a published citation carries the promise that its quote was verified
against the document, and there is no verification on a written one.
The cell keeps reading as succeeded, because the extraction did succeed.
curl --request PATCH \
--url https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/cells/{cellId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"answer": "Twelve months of fees paid.",
"review": "approved"
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/cells/{cellId}"
payload = {
"answer": "Twelve months of fees paid.",
"review": "approved"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({answer: 'Twelve months of fees paid.', review: 'approved'})
};
fetch('https://api.vaquill.ai/workspace/v1/matters/{matterId}/matrices/{matrixId}/cells/{cellId}', 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}/cells/{cellId}"
payload := strings.NewReader("{\n \"answer\": \"Twelve months of fees paid.\",\n \"review\": \"approved\"\n}")
req, _ := http.NewRequest("PATCH", 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": "cel_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"rowId": "row_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"columnId": "col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"status": "succeeded",
"answer": "Twelve months of fees paid.",
"citations": [
{
"quote": "in no event shall either party be liable for indirect damages",
"page": 1,
"chunkId": "chunk_00f1"
}
],
"confidence": 0.92,
"extractedAt": "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.
cel_ identifier of one cell, which is one document's answer to one question. Take it from GET .../matrices/{matrixId}/cells.
Body
Write a human answer into a cell, or record a review decision on it.
Writing answer promotes the cell to an edited state, and an edited,
approved or rejected cell is not re-run and not re-charged by a default
run. MatrixService._select_cells_for_run selects only pending,
error, not_found and not_applicable, schedule_run re-applies that
filter on its bulk reset, and extract_cell_by_id short-circuits before any
model call. force: true on a run has none of those guards and overwrites
the answer with no warning.
The cell keeps reading as succeeded, because the extraction job did
succeed. The review verdict is not published back on the cell for the same
reason the comments and decisions are not published at all: it is a
collaboration primitive, and this API publishes the five public statuses and
no sixth.
The answer to record for this cell, replacing whatever is there. There is no way to clear an answer back to empty; re-run the cell with force to have the extractor produce a fresh one.
1 - 20000"Twelve months of fees paid."
approved or rejected, recording what a reviewer decided about the answer. The extractor's own statuses cannot be written here: an integration writing extracted onto an answer no machine produced makes the grid unauditable.
approved, rejected "approved"
Response
Successful Response
One answer. answer is None on a succeeded cell means "not in this
document", which is a finding rather than a failure.
Public identifier for the cell, cel_ followed by 32 hex characters.
"cel_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
row_ identifier of the row this cell sits in. Resolve it against the matrix's rows.
"row_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
col_ identifier of the column this cell sits in. Resolve it against the matrix's columns.
"col_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
Extraction status for this one cell, using the same five public values as an operation.
queued, running, succeeded, failed, cancelled "succeeded"
The extracted answer. Null on a SUCCEEDED cell means the answer is not in that document, which is a finding rather than a failure. Null on a non-terminal cell means it has not run yet.
"Twelve months of fees paid."
Verified supporting quotes for the answer. An empty list on a succeeded cell with an answer means every candidate citation failed verification and was dropped.
Show child attributes
Show child attributes
The extractor's confidence in the answer, 0 to 1.
0.92
When this cell was last extracted (RFC 3339).
"2026-08-19T14:32:10Z"
Was this page helpful?

