curl --request PUT \
--url https://api.vaquill.ai/workspace/v1/playbooks/{playbookId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "MSA, buyer side"
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/playbooks/{playbookId}"
payload = { "name": "MSA, buyer side" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'MSA, buyer side'})
};
fetch('https://api.vaquill.ai/workspace/v1/playbooks/{playbookId}', 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/playbooks/{playbookId}"
payload := strings.NewReader("{\n \"name\": \"MSA, buyer side\"\n}")
req, _ := http.NewRequest("PUT", 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": "pbk_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"name": "MSA, buyer side",
"description": "Master services agreement with Acme for the 2026 platform rollout.",
"contractType": "msa",
"positions": {
"limitation_of_liability": {
"standardPosition": "Liability is capped at the fees paid in the preceding twelve months.",
"acceptableRange": "Between one and two times the fees paid in the preceding twelve months.",
"escalationTriggers": [
"value"
],
"fallbackLadder": [
"value"
],
"dealBreaker": "value",
"priority": "must_have",
"approvalLevel": "none",
"escalationConditions": [
{
"attribute": "clause_severity",
"operator": "eq",
"value": "1000000",
"escalateTo": "manager",
"note": "Escalated to GC: deal value over $1M."
}
],
"rationale": "Our standard position caps liability at fees paid in the preceding 12 months.",
"riskWeight": 4,
"enabled": true
}
},
"isDefault": false,
"sourceFilename": "msa-acme-v3.docx",
"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"
}Replace a playbook
Replace a playbook’s name, description and positions.
A clause type absent from positions is removed. Within a clause type that
is present, the authoring fields this API does not publish are preserved, so
a write through the API cannot delete work done in the product.
curl --request PUT \
--url https://api.vaquill.ai/workspace/v1/playbooks/{playbookId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "MSA, buyer side"
}
'import requests
url = "https://api.vaquill.ai/workspace/v1/playbooks/{playbookId}"
payload = { "name": "MSA, buyer side" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'MSA, buyer side'})
};
fetch('https://api.vaquill.ai/workspace/v1/playbooks/{playbookId}', 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/playbooks/{playbookId}"
payload := strings.NewReader("{\n \"name\": \"MSA, buyer side\"\n}")
req, _ := http.NewRequest("PUT", 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": "pbk_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6",
"name": "MSA, buyer side",
"description": "Master services agreement with Acme for the 2026 platform rollout.",
"contractType": "msa",
"positions": {
"limitation_of_liability": {
"standardPosition": "Liability is capped at the fees paid in the preceding twelve months.",
"acceptableRange": "Between one and two times the fees paid in the preceding twelve months.",
"escalationTriggers": [
"value"
],
"fallbackLadder": [
"value"
],
"dealBreaker": "value",
"priority": "must_have",
"approvalLevel": "none",
"escalationConditions": [
{
"attribute": "clause_severity",
"operator": "eq",
"value": "1000000",
"escalateTo": "manager",
"note": "Escalated to GC: deal value over $1M."
}
],
"rationale": "Our standard position caps liability at fees paid in the preceding 12 months.",
"riskWeight": 4,
"enabled": true
}
},
"isDefault": false,
"sourceFilename": "msa-acme-v3.docx",
"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
pbk_ identifier of the playbook. Take it from GET /v1/playbooks. A starter template is addressed by its slug instead, not by this.
Body
Replace a playbook's name, description and positions.
A PUT, and it replaces at the MAP level: a clause type absent from
positions is removed from the playbook. Within a clause type that IS
present, the five unpublished authoring fields are preserved (see
playbook_positions.PRESERVED_ON_WRITE), because the alternative is deleting
a lawyer's work with no error and no way to notice.
contractType is absent on purpose, and so is isDefault. Both are
explained in the module docstring.
Replacement display name. Required: this is a PUT, not a patch.
1 - 200"MSA, buyer side"
Replacement description, or null to clear it.
1000"Master services agreement with Acme for the 2026 platform rollout."
The COMPLETE set of positions after the write. Replacement happens at the map level: a clause type you omit is removed from the playbook. Within a clause type you do send, unpublished authoring fields set in the web app are preserved.
Show child attributes
Show child attributes
Response
Successful Response
One organization playbook, with every position it holds.
Positions are returned in full rather than summarized. A playbook is the input to a review, so a caller that cannot read the positions cannot tell what its reviews are being measured against, and a separate positions endpoint would make the common case two calls.
Public identifier, pbk_ followed by 32 hex characters.
"pbk_9f2c8b1e4a7d43c9b6e0f1a2c3d4e5f6"
The playbook's display name.
"MSA, buyer side"
Which contract type this playbook governs. Fixed at creation: changing it would silently redirect which reviews resolve it.
"msa"
Free-text description of what this playbook covers.
"Master services agreement with Acme for the 2026 platform rollout."
Every negotiating position the playbook holds, keyed by clause-type slug. Returned in full, because a caller that cannot read the positions cannot tell what its reviews are measured against.
Show child attributes
Show child attributes
True when reviews of this contract type resolve to this playbook if none is named. Read-only here: exactly one default per contract type is enforced by the database, and this API cannot set it.
false
Filename of the exemplar this playbook was extracted from, when it was imported rather than authored by hand.
"msa-acme-v3.docx"
When the playbook was created (RFC 3339).
"2026-08-19T14:32:10Z"
When the playbook was last modified (RFC 3339).
"2026-08-19T14:32:10Z"
Was this page helpful?

