curl --request POST \
--url https://api.vaquill.ai/workspace/v1/playbook-extractions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"documentId": "doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"contractType": "msa",
"useTrackedChanges": false
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/playbook-extractions"
payload = {
"documentId": "doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"contractType": "msa",
"useTrackedChanges": False
}
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({
documentId: 'doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6',
contractType: 'msa',
useTrackedChanges: false
})
};
fetch('https://api.vaquill.ai/workspace/v1/playbook-extractions', 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/playbook-extractions"
payload := strings.NewReader("{\n \"documentId\": \"doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6\",\n \"contractType\": \"msa\",\n \"useTrackedChanges\": false\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": "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"
}{
"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"
}Extract starter positions from a contract
Read starter positions out of one of your own signed contracts.
Answers 202 with an operation. Poll it, then read the extraction for the
positions it found.
Nothing is saved. The result comes back for you to review, and
playbooks.create is the separate call that adopts it: an extraction is a
model’s reading of a contract, and persisting a misclassified one as the
positions your automated reviews run against is a mistake nobody would see
until a review cited it. The published position shape is exactly the one
playbooks.create accepts, so adopting is a copy rather than a translation.
Send either a documentId you uploaded or contractText you already hold,
never both. useTrackedChanges reads a .docx’s Word revision marks and
extracts what a reviewer pushed FROM and TO, rather than the final positions.
curl --request POST \
--url https://api.vaquill.ai/workspace/v1/playbook-extractions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"documentId": "doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"contractType": "msa",
"useTrackedChanges": false
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/playbook-extractions"
payload = {
"documentId": "doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"contractType": "msa",
"useTrackedChanges": False
}
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({
documentId: 'doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6',
contractType: 'msa',
useTrackedChanges: false
})
};
fetch('https://api.vaquill.ai/workspace/v1/playbook-extractions', 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/playbook-extractions"
payload := strings.NewReader("{\n \"documentId\": \"doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6\",\n \"contractType\": \"msa\",\n \"useTrackedChanges\": false\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": "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"
}{
"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.
Headers
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.
Body
The contract to read positions out of. Exactly one source.
documentId or contractText, never both and never neither. Text is
accepted for the same reason reviews.create accepts it: the caller usually
has the contract in hand, and requiring an upload first would make the
cheapest integration a four-call dance. A documentId is the better choice
when the file is a DOCX whose structure matters, and it is REQUIRED for
tracked-changes extraction.
doc_ identifier of a document in this organization to read. Mutually exclusive with contractText.
"doc_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
The contract as plain text. Mutually exclusive with documentId. Use it when you already hold the text and do not need the file kept.
400000"MASTER SERVICES AGREEMENT\n\nThis Master Services Agreement is entered into as of 19 August 2026 between Acme Corporation, a Delaware corporation, and the Supplier identified on the signature page.\n\n8. LIMITATION OF LIABILITY. Supplier's total liability arising out of this Agreement shall not exceed the fees paid in the preceding twelve months, except for breach of confidentiality and indemnification for third-party intellectual property claims, which are uncapped.\n\n9. INDEMNIFICATION. Supplier shall defend and indemnify Acme Corporation against any third-party claim that the services infringe a United States patent, copyright or trade secret.\n\n11. TERM AND TERMINATION. The initial term is two years, renewing for successive one-year terms unless either party gives ninety days written notice. Acme Corporation may terminate for convenience on thirty days notice.\n\n12. GOVERNING LAW. This Agreement is governed by the laws of the State of Delaware, without regard to its conflict of laws rules."
Pin the contract type instead of detecting it. Omit to have it detected from the opening of the document, which costs nothing extra: it runs concurrently with the extraction.
64"msa"
Read the file's Word revision marks and extract what a reviewer pushed FROM and TO, rather than the final-state positions. Requires a documentId whose filename ends in .docx: revision marks exist only in a DOCX.
false
Response
Successful Response
One long-running operation, whatever kind of work it is.
Readable for OPERATION_RETENTION_DAYS after creation, per AIP-151.
Public identifier, op_ followed by 32 hex characters. Poll GET /v1/operations/{operationId} with it.
"op_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
What kind of work this is, for example matrix.run or draft.generate.
"matrix.run"
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.
queued, running, succeeded, failed, cancelled "succeeded"
When the operation was accepted (RFC 3339).
"2026-08-19T14:32:10Z"
When the operation reached a terminal status (RFC 3339). Present if and only if the status is terminal.
"2026-08-19T14:32:10Z"
mat_ identifier of the matter this work belongs to, when it belongs to one.
"mat_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
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'.
Show child attributes
Show child attributes
Why the work failed. Present only when status is failed. Partial success is succeeded with progress.done < progress.total, never an error.
Show child attributes
Show child attributes
How far along the work is, when the underlying job reports it. Absent does not mean no progress.
Show child attributes
Show child attributes
The X-Request-ID of the request that created this operation. Quote it in a support ticket.
"req_5f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
Was this page helpful?

