{"openapi":"3.1.0","info":{"title":"XDocs API","version":"1.0.0","description":"Drive XDocs from your own software: write and send documents for signature, publish tracked links, run data rooms, and read back who read what.\n\nAuthenticate with `Authorization: Bearer xdk_…`. Keys are created under Settings → Developer and carry scopes; a call outside a key's scopes answers 403 naming the scope it wanted.\n\nRate limit: 120 requests a minute per key. Every reply carries `x-ratelimit-limit`, `x-ratelimit-remaining` and `x-ratelimit-reset`; a 429 carries `retry-after`.\n\nLists are keyset-paginated: pass `?limit=` (max 100) and `?cursor=` from the previous page's `nextCursor`, which is opaque. Timestamps are ISO 8601 in UTC.\n\nFilters are strict: a value a filter does not recognise — a mistyped `?status=`, or a `?resolved=` that is not exactly `true` or `false` — answers 400 rather than a silently empty or unfiltered page.\n\nResponses are `{ data }` for a single resource and `{ data, nextCursor }` for a list. Errors are `{ error }`, plus `details` when a body failed validation."},"servers":[{"url":"https://xdocs.io/api/v1"}],"tags":[{"name":"Discovery","description":"What this key can do and where its links live. The first two calls any integration makes, and both are safe to call from anywhere a key is being checked."},{"name":"Documents","description":"The editable source of truth. An authored document carries its body as structured content; an uploaded one carries a PDF; a shared file carries any other type, uploaded in the app. Authored documents and PDFs take a signing list; all three take share links, rooms and workspace folders."},{"name":"Templates","description":"A document saved for reuse. Recipient slots and the fields bound to them are kept; the addresses and access codes are stripped, so a template can never quietly send to whoever signed last time."},{"name":"Envelopes","description":"A document out for signature. Sending freezes a snapshot, so later edits cannot change what somebody agreed to, and the completed PDF carries a certificate with the whole audit trail."},{"name":"Share links","description":"A tracked link to one document or one room, with its own gates. Every gate the share dialog offers is here under the same name the response returns it with, so you can read a link, change one field and send it back."},{"name":"Data rooms","description":"Many documents behind one set of gates, in folders, with reading attributed per file. A frozen room's contents are locked while its links keep serving them; an archived room is retired, and every link into it answers with a closed page until it is restored. Viewer groups, which narrow a room link to some of its files, are set up in the app."},{"name":"Agreements","description":"Confidentiality terms written once and picked by name on any link. Editing one re-asks everybody who accepted the old wording, while their record keeps the text they actually agreed to."},{"name":"Views and visitors","description":"Reading measured section by section. Time accrues only while a section is on screen and the tab is active, so these are attention numbers rather than tab-left-open numbers."},{"name":"Analytics","description":"The headline numbers behind the analytics page, and the attention profile of a single document."},{"name":"Viewer questions","description":"What readers asked from inside a shared link, and your answers, which are emailed back to them."},{"name":"File requests","description":"Ask named people for named documents. Each assignee gets their own upload link, and whatever arrives becomes a document in the workspace, filed where the request says."},{"name":"Webhooks","description":"Subscriptions an integration creates and removes on its own, one per thing it wants to hear about. This is the shape Zapier, Make and n8n expect, and a subscription is the same endpoint row the developer settings page shows with its delivery log — so these calls see and change the workspace's endpoints wherever they were made."},{"name":"Audit log","description":"Every recorded event across signing, sharing and documents. This is the evidence trail — what happened, to what, by whom, from where — as opposed to analytics, which is about attention."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"xdk_…"}}},"security":[{"bearerAuth":[]}],"paths":{"/":{"get":{"summary":"The catalogue: every resource, the scopes this key holds, the rate limit and the host tracked links are served on.","operationId":"get-root","tags":["Discovery"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"include","in":"query","required":false,"description":"`endpoints` adds `groups`: every endpoint with its parameters, the whole of this reference as data.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ version, scopes, allScopes, rateLimit{perMinute}, linkOrigin, baseUrl, pagination, documentation, openapi, resources[], webhookEvents[], groups? }. `linkOrigin` is the account's verified custom domain when it has one, so build link URLs from it rather than assuming ours."}}}},"/me":{"get":{"summary":"Who this key acts for: the workspace, its plan and the key's scopes.","operationId":"get-me","tags":["Discovery"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"{ data: { workspaceId, name, email, scopes, plan, origin } }"}}}},"/openapi.json":{"get":{"summary":"This same surface as an OpenAPI 3.1 document, for generating a client.","operationId":"get-openapijson","tags":["Discovery"],"security":[],"parameters":[],"responses":{"200":{"description":"An OpenAPI document. No key required, and not counted against a rate limit."}}}},"/documents":{"get":{"summary":"Your documents, most recently edited first.","operationId":"get-documents","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"q","in":"query","required":false,"description":"Searches titles and body text.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"`draft` or `locked` (out for signature). Anything else is a 400.","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"description":"`xdoc` for authored, `pdf` for uploaded, `file` for a shared file. Anything else is a 400.","schema":{"type":"string"}},{"name":"folderId","in":"query","required":false,"description":"Documents filed in one workspace folder.","schema":{"type":"string"}},{"name":"inLibrary","in":"query","required":false,"description":"`true` for the curated library only.","schema":{"type":"boolean"}},{"name":"trashed","in":"query","required":false,"description":"`true` lists deleted documents instead of live ones.","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Document[], nextCursor } — id, title, kind, status, pageCount, activeEnvelopeId, createdAt, updatedAt"}}},"post":{"summary":"Create a document from Markdown, HTML, document JSON, or one of your saved templates.","operationId":"post-documents","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"1–200 characters. Required, unless `templateId` is given — then it defaults to the template's name."},"markdown":{"type":"string","description":"The body most callers have, up to 500,000 characters. Headings, both list kinds, quotes, code fences, rules, GFM pipe tables and `$…$` / `$$…$$` mathematics are all read; images are not. Converted on the way in, and conversion losses come back in `warnings`."},"html":{"type":"string","description":"An alternative body, for callers holding HTML. Up to 1,000,000 characters."},"content":{"type":"object","description":"Raw document JSON with `type: \"doc\"`, for callers holding that. Up to 1,000,000 characters serialized."},"templateId":{"type":"string","description":"Start from a saved template, signature blocks already in place. Cannot be combined with a body. Any `recipients` sent alongside fill the template's slots in order, so those blocks stay bound to them; a recipient who omits `role` or `routingOrder` keeps the slot's."},"recipients":{"type":"array","items":{},"description":"The draft signing list, up to 30. `role` is `signer` (the default) or `viewer`; `routingOrder` 1–99, defaulting to 1; `accessCode` (4–40 characters) is an out-of-band code that person must enter before signing."},"folderId":{"type":"string","description":"File it in one of your workspace folders."}},"required":[]}}}},"responses":{"201":{"description":"201 { data: Document, warnings: string[] } — the document in the shape GET /documents/:id returns"},"400":{"description":"No title for a document that is not from a template, or a template and a body in the same request."},"404":{"description":"No such template."},"422":{"description":"The plan's document ceiling has been reached, or the folder is not in your workspace."}}}},"/documents/upload":{"post":{"summary":"Create a document from a PDF.","operationId":"post-documents-upload","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"title","in":"query","required":false,"description":"Overrides the filename as the title.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","description":"Or send the raw PDF as the body with an `x-filename` header. 25 MB maximum."}},"required":[]}}}},"responses":{"201":{"description":"201 { data: Document & { hasTextLayer } } — `hasTextLayer` false means a scan whose words cannot be read or searched."},"400":{"description":"Not a PDF, unreadable, or has no pages."},"422":{"description":"Larger than 25 MB, or the plan's ceiling has been reached."}}}},"/documents/{id}":{"get":{"summary":"One document, with its signing list and what file sits under it.","operationId":"get-documents-by-id","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"`content` adds the body, which is the largest thing stored and so is opt-in.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Document & { folderId, inLibrary, deletedAt, recipients: [{ id, name, email, role, routingOrder, color, hasAccessCode }], source{filename, contentType, byteSize, hasTextLayer} | null, content? } } — an access code is reported as set, never repeated back"}}},"patch":{"summary":"Change a draft. A new body replaces the old one, which is snapshotted to version history first.","operationId":"patch-documents-by-id","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"1–200 characters."},"markdown":{"type":"string","description":"Replaces the body. Same limits as POST."},"html":{"type":"string","description":"Replaces the body."},"content":{"type":"object","description":"Replaces the body."},"recipients":{"type":"array","items":{},"description":"Replaces the signing list, up to 30. Send back a recipient's `id` — or their unchanged address — to correct a name or email in place: their id is what the signature fields in the body are bound to, and a recipient who arrives without one is treated as somebody new, with nothing yet to sign."},"folderId":{"type":"string","description":"A workspace folder, or null to take it out of one."},"inLibrary":{"type":"boolean","description":"Add it to or remove it from the curated library."},"versionLabel":{"type":"string","description":"Names the snapshot taken before the body is replaced. Up to 120 characters."}},"required":[]}}}},"responses":{"200":{"description":"{ data: Document, warnings: string[] } — the document in the shape GET /documents/:id returns"},"409":{"description":"A new body for a document out for signature. Void the envelope first."},"422":{"description":"A body for an uploaded file, which is replaced with POST /documents/:id/file instead; or a folder that is not in your workspace."}}},"delete":{"summary":"Move a document to the trash, where it can be restored.","operationId":"delete-documents-by-id","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"purge","in":"query","required":false,"description":"`true` deletes it outright, and only from the trash.","schema":{"type":"boolean"}}],"responses":{"204":{"description":"No content."},"409":{"description":"It is out for signature; or a purge was asked for on a document that is not in the trash, or that has been sent for signature and is kept as part of that record."}}}},"/documents/{id}/restore":{"post":{"summary":"Bring a document back from the trash.","operationId":"post-documents-by-id-restore","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Document }"},"409":{"description":"That document is not in the trash."},"422":{"description":"The plan's document ceiling has been reached; trashed documents do not count toward it."}}}},"/documents/{id}/file":{"get":{"summary":"The file under an uploaded document: the current source PDF, or a shared file (`kind: file`) in its own type.","operationId":"get-documents-by-id-file","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The file bytes, with the stored content type and filename."},"404":{"description":"An authored document, which has no source file — export it instead."}}},"post":{"summary":"Replace the file under an uploaded document. It keeps its id and every link to it; the outgoing file becomes a version.","operationId":"post-documents-by-id-file","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","description":"Or the raw PDF as the body with an `x-filename` header. 25 MB maximum."}},"required":[]}}}},"responses":{"200":{"description":"{ data: { documentId, previousVersionId, pageCount, previousPageCount, hasTextLayer, droppedFields } } — `previousVersionId` holds the outgoing file; `droppedFields` counts field placements on pages the new file no longer has"},"400":{"description":"Not a PDF, unreadable, or has no pages."},"409":{"description":"The document is out for signature, or is not an uploaded PDF."},"422":{"description":"Larger than 25 MB."},"503":{"description":"The file could not be stored. Nothing changed; safe to retry."}}}},"/documents/{id}/export":{"get":{"summary":"The document as a file, typeset the way the app exports it.","operationId":"get-documents-by-id-export","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"`pdf` (default), `docx` or `md`. Anything else is a 400.","schema":{"type":"string"}}],"responses":{"200":{"description":"The file bytes."},"409":{"description":"An uploaded PDF can only be exported as PDF."}}}},"/documents/{id}/versions":{"get":{"summary":"History, newest first: the restore points somebody named and the snapshots the document took of itself.","operationId":"get-documents-by-id-versions","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Up to 100. Defaults to 50.","schema":{"type":"integer"}}],"responses":{"200":{"description":"{ data: Version[] } — id, documentId, title, kind, pageCount, label, automatic, createdBy, createdAt. `automatic` is true for the snapshots the document took of itself, which have no label."}}},"post":{"summary":"Mark a restore point at the document as it stands.","operationId":"post-documents-by-id-versions","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","description":"What this point is, up to 120 characters. Defaults to naming the API."}},"required":[]}}}},"responses":{"201":{"description":"201 { data: Version }"}}}},"/documents/{id}/versions/{versionId}":{"get":{"summary":"One version.","operationId":"get-documents-by-id-versions-by-versionId","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"`content` adds the body it preserved.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Version }"}}},"post":{"summary":"Put a version back. What it replaces is snapshotted first, so a restore is itself undoable.","operationId":"post-documents-by-id-versions-by-versionId","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Document }"},"409":{"description":"The document is out for signature."},"422":{"description":"The file stored with that version could not be read, so restoring it would leave the document half-changed."}}},"delete":{"summary":"Drop a snapshot. The document is untouched.","operationId":"delete-documents-by-id-versions-by-versionId","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."},"409":{"description":"A tracked link is pinned to this version; `details.links` names them. Re-point them first — an unpinned link quietly starts showing the live document."}}}},"/documents/{id}/signature-blocks":{"post":{"summary":"Append somewhere to sign — name, signature and date, bound to one recipient. The step between writing a document through the API and being able to send it, because an envelope refuses to go to a recipient with nothing to complete.","operationId":"post-documents-by-id-signature-blocks","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"recipientId":{"type":"string","description":"A recipient on the document. Optional when there is only one."},"email":{"type":"string","description":"Identify that recipient by address instead."},"heading":{"type":"string","description":"The label above the block, usually the party's role in the agreement. Up to 120 characters; defaults to the recipient's name."}},"required":[]}}}},"responses":{"201":{"description":"201 { data: Document, addedFor: { recipientId, name, email }, totalFields } — the body before the block is snapshotted to version history first; `totalFields` counts every field now in the body, across all recipients"},"409":{"description":"The document is out for signature."},"422":{"description":"No recipients yet, a recipient who is not on the document, several recipients and none named, or an uploaded PDF — whose fields are placed by page coordinate in the editor."}}}},"/documents/{id}/comments":{"get":{"summary":"The comment thread, oldest first.","operationId":"get-documents-by-id-comments","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"resolved","in":"query","required":false,"description":"`false` for what is still open.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"{ data: Comment[] } — id, documentId, parentId, authorName, authorEmail, body, quote, resolved, createdAt. A reply carries the `parentId` of the comment that opened its thread."}}},"post":{"summary":"Leave a comment. The owner, the thread and anyone @-mentioned are emailed, as they are from the editor.","operationId":"post-documents-by-id-comments","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","description":"Up to 10,000 characters. `@name` mentions are notified."},"parentId":{"type":"string","description":"Reply into an existing thread: the id of the comment that opened it. Threads are one level deep."},"quote":{"type":"string","description":"The passage being commented on, up to 2,000 characters."}},"required":["body"]}}}},"responses":{"201":{"description":"201 { data: Comment, notified: string[] } — `notified` is the addresses emailed"},"422":{"description":"`parentId` is not a comment on this document, or is itself a reply."}}}},"/documents/{id}/comments/{commentId}":{"patch":{"summary":"Resolve or reopen any comment on the document, or correct the wording of one of your own.","operationId":"patch-documents-by-id-comments-by-commentId","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"resolved":{"type":"boolean"},"body":{"type":"string","description":"Only on a comment this account wrote — a collaborator's words are theirs to change."}},"required":[]}}}},"responses":{"200":{"description":"{ data: Comment }"},"403":{"description":"`body` was sent for a comment somebody else wrote. Nothing is changed, `resolved` included."},"422":{"description":"`resolved` was sent for a reply. Threads are resolved on their first comment."}}},"delete":{"summary":"Remove one of your own comments and its replies.","operationId":"delete-documents-by-id-comments-by-commentId","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"commentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."},"403":{"description":"The comment was written by somebody else. Reply to it or resolve the thread instead."}}}},"/folders":{"get":{"summary":"The workspace's document folders, in the order the dashboard shows them — where the `folderId` a document is filed under comes from. Folders nest; the whole tree comes back in one call, so build it from `parentId` rather than asking per level.","operationId":"get-folders","tags":["Documents"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[],"responses":{"200":{"description":"{ data: Folder[] } — id, name, parentId (null at the top level), position, documentCount (live documents filed directly in it, not in its subfolders), createdAt, updatedAt"}}},"post":{"summary":"A folder, after the existing ones in the same place. File documents into it with `folderId` on POST or PATCH /documents.","operationId":"post-folders","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–120 characters."},"parentId":{"type":"string","description":"Nest it inside one of your folders. Omit for the top level."}},"required":["name"]}}}},"responses":{"201":{"description":"201 { data: Folder }"},"404":{"description":"No such parent folder in your workspace."},"422":{"description":"That would nest the folder more than 8 levels deep."}}}},"/folders/{id}":{"patch":{"summary":"Rename a folder, reorder it among its siblings, or move it — with everything under it — into another folder.","operationId":"patch-folders-by-id","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–120 characters."},"position":{"type":"integer","description":"Orders it among the folders sharing its parent."},"parentId":{"type":"string","description":"Move it inside another folder, or null for the top level. Omit to leave it where it is."}},"required":[]}}}},"responses":{"200":{"description":"{ data: Folder }"},"404":{"description":"No such folder, or no such parent folder in your workspace."},"422":{"description":"A move into the folder itself or into one of its own subfolders, or one that would take the branch more than 8 levels deep."}}},"delete":{"summary":"Remove a folder. Its documents and its subfolders move up a level, into whatever it was itself inside, rather than going with it.","operationId":"delete-folders-by-id","tags":["Documents"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/templates":{"get":{"summary":"Saved templates, most recently changed first.","operationId":"get-templates","tags":["Templates"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Template[], nextCursor } — id, name, description, kind, pageCount, recipients: [{ id, name, role, routingOrder }], useCount, createdAt, updatedAt"}}},"post":{"summary":"Save one of your documents as a template.","operationId":"post-templates","tags":["Templates"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"documentId":{"type":"string","description":"The document to copy."},"name":{"type":"string","description":"1–200 characters. Defaults to the document's title plus “template”."},"description":{"type":"string","description":"Up to 2,000 characters."}},"required":["documentId"]}}}},"responses":{"201":{"description":"201 { data: Template }"}}}},"/templates/{id}":{"get":{"summary":"One template.","operationId":"get-templates-by-id","tags":["Templates"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"`content` adds the body.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Template }"}}},"patch":{"summary":"Rename or re-describe a template. Its body is fixed at save time.","operationId":"patch-templates-by-id","tags":["Templates"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–200 characters."},"description":{"type":"string","description":"Up to 2,000 characters."}},"required":[]}}}},"responses":{"200":{"description":"{ data: Template }"}}},"delete":{"summary":"Delete a template. Documents made from it are untouched.","operationId":"delete-templates-by-id","tags":["Templates"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/envelopes":{"get":{"summary":"Envelopes you sent, newest first, each with its parties.","operationId":"get-envelopes","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:read"]}],"parameters":[{"name":"status","in":"query","required":false,"description":"`sent`, `completed`, `declined`, `voided` or `expired`. Anything else is a 400.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Envelope[], nextCursor } — id, documentId, title, kind, pageCount, subject, message, senderName, senderEmail, status, sequential, contentHash, completionHash, expiresAt, reminderEveryDays, lastReminderAt, sentAt, completedAt, voidedAt, voidReason, recipients: [{ id, name, email, role, routingOrder, status, viewedAt, signedAt, declinedAt, declineReason, notifiedAt, deliveryFailedAt, deliveryError, authMethod, authenticatedAt, delegatedToEmail, delegatedFromId }]. `deliveryFailedAt` is set when the signing email bounced; `authMethod` is `email` or `email+access_code`, and the code itself is never returned."}}},"post":{"summary":"Send a prepared document for signature. Recipients and field placement come from the document, because that is where they are authored.","operationId":"post-envelopes","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"documentId":{"type":"string","description":"A draft with at least one signer, each with a name, an address and at least one field to complete — see POST /documents/:id/signature-blocks."},"subject":{"type":"string","description":"The email subject, up to 300 characters. Defaults to “Please sign: <title>”."},"message":{"type":"string","description":"A note inside the email, up to 2,000 characters."},"sequential":{"type":"boolean","description":"True routes signers one after another; false sends to everybody at once."},"expiresAt":{"type":"string","format":"date-time","description":"After this the envelope stops accepting signatures."},"reminderEveryDays":{"type":"integer","description":"Nudge whoever is holding it up on this cadence."}},"required":["documentId"]}}}},"responses":{"201":{"description":"201 { data: Envelope, delivery: [{ email, delivered, reason }] } — check `delivery`: the envelope is real and its links work even when a notification bounced."},"402":{"description":"The plan's sends for this month are used and the credit balance will not cover another. Nothing was charged; top up on the billing page or upgrade the plan."},"404":{"description":"No such document."},"409":{"description":"That document is already out for signature — including when a concurrent send claimed it first, so a retried request cannot mail one agreement twice."},"422":{"description":"Not ready to send: no signers, a recipient missing a name or address, a signer with no field to complete, a field bound to a recipient no longer on the list, unresolved suggestions in the body, a placeholder left in it (`[COMPANY NAME]`, “TBD”) or a signature line with no field — or a shared file, which cannot be signed. The message names which."},"503":{"description":"Billing did not answer, so nothing was sent or charged. Safe to retry."}}}},"/envelopes/{id}":{"get":{"summary":"Full status, with every party and every field.","operationId":"get-envelopes-by-id","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"`signingUrls` adds each outstanding recipient's signing link. That link is the capability to sign, so it needs the envelopes:write scope.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Envelope & { recipients[], fields: [{ id, recipientId, type, label, required, completedAt }] } } — with `signingUrls`, each recipient also carries `signingUrl`, null for anyone who has signed, declined or passed it on"},"403":{"description":"Signing links were asked for by a key that cannot send."}}}},"/envelopes/{id}/remind":{"post":{"summary":"Nudge whoever the envelope is waiting on — on a sequential envelope that is one person, not everybody unsigned.","operationId":"post-envelopes-by-id-remind","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Envelope, reminded: number }"},"409":{"description":"The envelope has ended, or nobody is currently waiting."}}}},"/envelopes/{id}/void":{"post":{"summary":"Cancel an envelope in flight. Everyone outstanding is told the reason and the document returns to draft.","operationId":"post-envelopes-by-id-void","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","description":"Up to 500 characters. Sent to the recipients and written to the audit trail."}},"required":["reason"]}}}},"responses":{"200":{"description":"{ data: Envelope }"},"409":{"description":"The envelope has already ended."}}}},"/envelopes/{id}/recipients/{recipientId}/reassign":{"post":{"summary":"Move a signature to somebody else. The fields follow the person, and the original stays on the envelope as `delegated`.","operationId":"post-envelopes-by-id-recipients-by-recipientId-reassign","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"recipientId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"reason":{"type":"string","description":"Up to 500 characters. Recorded in the trail."}},"required":["name","email"]}}}},"responses":{"200":{"description":"{ data: Envelope, replacementId } — `replacementId` is the new recipient's id"},"409":{"description":"The envelope has already ended."},"422":{"description":"That recipient declined, has already signed, already passed it on, or the address is unchanged."}}}},"/envelopes/{id}/pdf":{"get":{"summary":"The executed document with every signature and the certificate of completion.","operationId":"get-envelopes-by-id-pdf","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The PDF bytes. For a completed envelope, the copy archived at completion rather than a fresh render."},"422":{"description":"The PDF could not be built."}}}},"/envelopes/{id}/certificate":{"get":{"summary":"The same evidence as data: signers, consent records, authentication, the audit trail and the integrity digests.","operationId":"get-envelopes-by-id-certificate","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Certificate } — the digests are recomputed from the stored rows and reported as `documentHashVerified` / `completionHashVerified`, not merely echoed back."}}}},"/envelopes/{id}/attachments":{"get":{"summary":"Files a signer returned, as metadata.","operationId":"get-envelopes-by-id-attachments","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Attachment[] } — id, envelopeId, recipientId, fieldId, filename, contentType, byteSize, sha256, uploadedAt, newest first. `sha256` is the digest of the bytes as received."}}}},"/envelopes/{id}/attachments/{attachmentId}":{"get":{"summary":"The bytes of one returned file, streamed through rather than exposed as a storage URL.","operationId":"get-envelopes-by-id-attachments-by-attachmentId","tags":["Envelopes"],"security":[{"bearerAuth":["envelopes:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The file bytes."}}}},"/links":{"get":{"summary":"Tracked links, newest first, each with its URL on your link origin.","operationId":"get-links","tags":["Share links"],"security":[{"bearerAuth":["links:read"]}],"parameters":[{"name":"documentId","in":"query","required":false,"description":"Links to one document.","schema":{"type":"string"}},{"name":"dataRoomId","in":"query","required":false,"description":"Links to one room.","schema":{"type":"string"}},{"name":"active","in":"query","required":false,"description":"`true` for links that still answer.","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Link[], nextCursor }"}}},"post":{"summary":"Publish a link to one document or one room.","operationId":"post-links","tags":["Share links"],"security":[{"bearerAuth":["links:write"]}],"parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"documentId":{"type":"string","description":"Exactly one of this and `dataRoomId`."},"dataRoomId":{"type":"string","description":"Exactly one of this and `documentId`."},"name":{"type":"string","description":"How the link is labelled in analytics. Defaults to “Shared link”."},"active":{"type":"boolean","description":"Defaults to true."},"isPublic":{"type":"boolean","description":"Publish the document: anyone with the address reads it immediately, and search engines are asked to index the page. Forces `requireEmail`, `requireEmailVerification`, `password` and `requireNda` off, whatever else the same request sets. Defaults to false, so a link is private unless you say otherwise."},"requireEmail":{"type":"boolean","description":"Ask a visitor who they are. Defaults to true, and ignored when `isPublic` is set."},"requireEmailVerification":{"type":"boolean","description":"Send a six-digit code to that address and check it. Implies `requireEmail`."},"password":{"type":"string","description":"Protect the link. Null removes it."},"expiresAt":{"type":"string","format":"date-time"},"maxViews":{"type":"integer","description":"Stop answering after this many visits."},"pinnedVersionId":{"type":"string","description":"Serve one saved version rather than the live document."},"allowDownload":{"type":"boolean","description":"Defaults to false."},"watermark":{"type":"boolean","description":"Defaults to true."},"watermarkConfig":{"type":"object","description":"`{ text, position, opacity, rotation, fontSize, color }`, all optional and merged over the current values. `text` takes the placeholders {email}, {date}, {time}, {ip} and {link}; `position` is tiled, center or footer; `opacity` 1–100; `rotation` -90–90; `fontSize` 8–96; `color` a six-digit hex. Null clears it back to the default."},"requireNda":{"type":"boolean","description":"Ask the visitor to accept terms before they can read."},"ndaText":{"type":"string","description":"Terms written on the link itself."},"agreementId":{"type":"string","description":"Terms from your agreements library instead. Editing that agreement re-asks everyone who accepted the old wording."},"allowedEmails":{"type":"array","items":{},"description":"Only these addresses — or anyone at `allowedDomains`, when both are set. Up to 200 entries."},"allowedDomains":{"type":"array","items":{},"description":"Only addresses at these domains, matched exactly: `acme.com` does not admit `eu.acme.com`. Up to 200."},"blockedEmails":{"type":"array","items":{},"description":"Never these. An entry without an `@` in the middle — `rival.com` or `@rival.com` — is a domain and blocks everybody at it. Up to 200."},"notifyOnView":{"type":"boolean","description":"Email you when somebody opens it. Defaults to true."},"screenshotProtection":{"type":"boolean","description":"Deter casual copying: printing is blocked and the page hides when the window loses focus. Defaults to false."},"allowAssistant":{"type":"boolean","description":"Let the reader ask questions about the document. Defaults to false."},"allowAudio":{"type":"boolean","description":"Let the reader have the document read aloud, choosing a voice and a speed. Defaults to false."},"allowFeedback":{"type":"boolean","description":"Show a reaction bar under the document. Defaults to false."},"bulkDownloadOtp":{"type":"boolean","description":"Room links only: make a visitor confirm an emailed code before a zip of everything. Defaults to true."},"tags":{"type":"array","items":{},"description":"Your own labels for filtering links: up to 20, each one word of up to 32 characters, stored lowercased."},"captureFields":{"type":"array","items":{},"description":"Extra questions asked with the email, up to 8. `type` is text, select or checkbox and defaults to text; a select needs `options`. `id` is minted from the label when you omit it, and is the key the answers come back under on a view."},"ogTitle":{"type":"string","description":"What a chat app or social card shows when the link is pasted. Defaults to the document or room name."},"ogDescription":{"type":"string","description":"The line under that title."},"ogImageUrl":{"type":"string","description":"The card's picture, an http or https address. Defaults to the XDocs card. 1200×630 previews best."},"ogFaviconUrl":{"type":"string","description":"The icon in the browser tab on the viewer page."}},"required":[]}}}},"responses":{"201":{"description":"201 { data: Link } — including `url`, `slug` and `watermarkConfig` as resolved"},"422":{"description":"A pinned version or agreement that is not yours, or the plan's link ceiling has been reached."}}}},"/links/{id}":{"get":{"summary":"One link and its gates. The password is reported as `hasPassword`, never returned.","operationId":"get-links-by-id","tags":["Share links"],"security":[{"bearerAuth":["links:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Link } — id, name, slug, url, documentId, dataRoomId, groupId, viewCount, hasPassword, createdAt, updatedAt, and every setting POST accepts under the same name. `ndaText` is null while an `agreementId` supplies the terms. `groupId` marks a room link made in the app for one viewer group: it admits only that group's members and shows only the files the group was given, whatever `allowDownload` says."}}},"patch":{"summary":"Change any setting; omitted fields are kept. Tightening a gate re-gates visitors who already cleared it — a new password or new terms are asked for again, and the address lists are re-checked on every visit, so a newly blocked address is turned away on its next one.","operationId":"patch-links-by-id","tags":["Share links"],"security":[{"bearerAuth":["links:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"…":{"type":"string","description":"Every setting POST accepts, all optional. `documentId` and `dataRoomId` are not among them: a link points at what it was made for."}},"required":[]}}}},"responses":{"200":{"description":"{ data: Link }"},"422":{"description":"A pinned version that is not this document's (or any pin on a room link), an agreement that is not in your library, or an `ogImageUrl` / `ogFaviconUrl` that is not http or https. A viewer-group link cannot be made public, or switched back on once its group has been deleted."}}},"delete":{"summary":"The link stops answering. Its visits are kept, because they are evidence about who read what.","operationId":"delete-links-by-id","tags":["Share links"],"security":[{"bearerAuth":["links:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/rooms":{"get":{"summary":"Your data rooms, most recently changed first.","operationId":"get-rooms","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:read"]}],"parameters":[{"name":"archived","in":"query","required":false,"description":"`false` for the rooms the app's room list shows, `true` for the archived ones. Omitted, both.","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Room[], nextCursor } — id, name, description, frozenAt, archivedAt, createdAt, updatedAt"}}},"post":{"summary":"An empty room; file documents into it next.","operationId":"post-rooms","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–200 characters."},"description":{"type":"string","description":"Up to 2,000 characters."}},"required":["name"]}}}},"responses":{"201":{"description":"201 { data: Room & { folders: [], documents: [] } }"},"422":{"description":"The plan's room ceiling has been reached."}}}},"/rooms/{id}":{"get":{"summary":"The room with its state, folders and filed documents, in the order an ordinary room link shows them.","operationId":"get-rooms-by-id","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Room & { folders: Folder[], documents: [{ documentId, folderId, position, title, kind, addedAt }] } } — documents in the trash are left out"}}},"patch":{"summary":"Rename or re-describe a room, freeze or unfreeze it, archive or restore it. None of these changes what is filed, so a frozen room accepts them.","operationId":"patch-rooms-by-id","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–200 characters."},"description":{"type":"string","description":"Up to 2,000 characters."},"frozen":{"type":"boolean","description":"`true` locks the contents — nothing filed, moved or removed — while links keep serving exactly what is there."},"archived":{"type":"boolean","description":"`true` retires the room: every link into it answers with a closed page. `false` puts it all back."}},"required":[]}}}},"responses":{"200":{"description":"{ data: Room & { folders[], documents[] } }"}}},"delete":{"summary":"To the trash. Links into the room stop answering at once; the documents themselves are untouched.","operationId":"delete-rooms-by-id","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/rooms/{id}/documents":{"get":{"summary":"What is filed in the room, and where.","operationId":"get-rooms-by-id-documents","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: [{ documentId, folderId, position, title, kind, addedAt }] }"}}},"post":{"summary":"File one of your documents. Idempotent: filing one already there moves it, which is what a sync wants.","operationId":"post-rooms-by-id-documents","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"documentId":{"type":"string","description":"One of your live documents."},"folderId":{"type":"string","description":"A folder in this room, or null for the top level."}},"required":["documentId"]}}}},"responses":{"201":{"description":"201 { data: RoomDocument[] } — everything now filed in the room, not only this document"},"404":{"description":"No such document, or no such folder in this room."},"409":{"description":"The room is frozen. Unfreeze it with PATCH /rooms/:id to change its contents."}}}},"/rooms/{id}/documents/{documentId}":{"patch":{"summary":"Move a filed document between folders or along the order.","operationId":"patch-rooms-by-id-documents-by-documentId","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"documentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"folderId":{"type":"string","description":"A folder in this room, or null for the top level."},"position":{"type":"integer"}},"required":[]}}}},"responses":{"200":{"description":"{ data: RoomDocument[] }"},"404":{"description":"That document is not in this room, or no such folder in it."},"409":{"description":"The room is frozen. Unfreeze it with PATCH /rooms/:id to change its contents."}}},"delete":{"summary":"Take a document out of the room. The document itself stays.","operationId":"delete-rooms-by-id-documents-by-documentId","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"documentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."},"409":{"description":"The room is frozen. Unfreeze it with PATCH /rooms/:id to change its contents."}}}},"/rooms/{id}/folders":{"get":{"summary":"The room's folders, in display order.","operationId":"get-rooms-by-id-folders","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Folder[] } — id, dataRoomId, name, position, createdAt"}}},"post":{"summary":"A folder, appended after the existing ones.","operationId":"post-rooms-by-id-folders","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–200 characters."}},"required":["name"]}}}},"responses":{"201":{"description":"201 { data: Folder }"},"409":{"description":"The room is frozen. Unfreeze it with PATCH /rooms/:id to change its contents."}}}},"/rooms/{id}/folders/{folderId}":{"patch":{"summary":"Rename or reorder a folder.","operationId":"patch-rooms-by-id-folders-by-folderId","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"folderId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–200 characters."},"position":{"type":"integer"}},"required":[]}}}},"responses":{"200":{"description":"{ data: Folder }"},"409":{"description":"The room is frozen. Unfreeze it with PATCH /rooms/:id to change its contents."}}},"delete":{"summary":"Remove a folder. Its documents return to the top level rather than leaving the room.","operationId":"delete-rooms-by-id-folders-by-folderId","tags":["Data rooms"],"security":[{"bearerAuth":["rooms:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"folderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."},"409":{"description":"The room is frozen. Unfreeze it with PATCH /rooms/:id to change its contents."}}}},"/agreements":{"get":{"summary":"The library, most recently edited first, with how much each one is used.","operationId":"get-agreements","tags":["Agreements"],"security":[{"bearerAuth":["links:read"]}],"parameters":[],"responses":{"200":{"description":"{ data: Agreement[] } — id, name, body, requireName, linkCount, acceptedCount, createdAt, updatedAt"}}},"post":{"summary":"Write terms once; pick them by id on any link.","operationId":"post-agreements","tags":["Agreements"],"security":[{"bearerAuth":["links:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–120 characters. How it is picked on a link."},"body":{"type":"string","description":"20–20,000 characters. The exact text a visitor is asked to accept."},"requireName":{"type":"boolean","description":"Also ask the visitor to type their name. Defaults to false."}},"required":["name","body"]}}}},"responses":{"201":{"description":"201 { data: Agreement }"}}}},"/agreements/{id}":{"get":{"summary":"One agreement with its usage counts.","operationId":"get-agreements-by-id","tags":["Agreements"],"security":[{"bearerAuth":["links:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Agreement }"}}},"patch":{"summary":"Change the wording. New wording is a new agreement for everyone who accepted the old one.","operationId":"patch-agreements-by-id","tags":["Agreements"],"security":[{"bearerAuth":["links:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"1–120 characters. Renaming re-asks nobody."},"body":{"type":"string","description":"20–20,000 characters."},"requireName":{"type":"boolean"}},"required":[]}}}},"responses":{"200":{"description":"{ data: Agreement, regatedLinks: number } — `regatedLinks` is how many links now ask again, and is 0 unless the wording itself changed"}}},"delete":{"summary":"Remove from the library. Links using it keep the gate, with the text copied onto them, so deleting never quietly opens a document; link presets that named it keep its words the same way.","operationId":"delete-agreements-by-id","tags":["Agreements"],"security":[{"bearerAuth":["links:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/views":{"get":{"summary":"Visits, newest first. A visit counts once every gate was cleared.","operationId":"get-views","tags":["Views and visitors"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"documentId","in":"query","required":false,"schema":{"type":"string"}},{"name":"dataRoomId","in":"query","required":false,"schema":{"type":"string"}},{"name":"shareLinkId","in":"query","required":false,"schema":{"type":"string"}},{"name":"email","in":"query","required":false,"schema":{"type":"string"}},{"name":"since","in":"query","required":false,"description":"Visits started at or after this.","schema":{"type":"string","format":"date-time"}},{"name":"includeUnopened","in":"query","required":false,"description":"`true` also lists visits that never cleared the gates.","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: View[], nextCursor } — id, shareLinkId, documentId, dataRoomId, viewerEmail, emailVerified, ndaAcceptedAt, ndaText (the exact terms accepted, whatever the link says now), ndaSignedName, openedAt (null until every gate was cleared), lastOpenedAt, startedAt, lastSeenAt, totalMs (active reading, not wall clock), opens (separate sittings), completion, downloadedAt, captureAnswers (keyed by the link's capture field `id`), country, city, referrer, userAgent, ipAddress"},"400":{"description":"`since` is not a timestamp."}}}},"/views/{id}":{"get":{"summary":"One visit with its per-section reading — per page for a PDF.","operationId":"get-views-by-id","tags":["Views and visitors"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: View & { sections: [{ documentId, index, heading, visibleMs }] } } — a room visit carries several documents' sections, told apart by `documentId`"}}}},"/visitors":{"get":{"summary":"Visits grouped by the person who made them: not “opened nine times” but “this person has read four documents for an hour”.","operationId":"get-visitors","tags":["Views and visitors"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"documentId","in":"query","required":false,"schema":{"type":"string"}},{"name":"dataRoomId","in":"query","required":false,"schema":{"type":"string"}},{"name":"shareLinkId","in":"query","required":false,"schema":{"type":"string"}},{"name":"email","in":"query","required":false,"description":"One visitor, by the address they gave.","schema":{"type":"string"}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Visitor[], nextCursor } — email, views, documents, totalMs, avgCompletion, firstSeenAt, lastSeenAt, verified, acceptedNda, downloaded. Only visits that captured an address and cleared the gates are counted."},"400":{"description":"`since` is not a timestamp."}}}},"/visitors/{email}":{"get":{"summary":"One person, with their most recent visits.","operationId":"get-visitors-by-email","tags":["Views and visitors"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"email","in":"path","required":true,"description":"URL-encoded email address.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Visitor & { views: View[] } } — the latest 100 visits"},"400":{"description":"The path is not a URL-encoded email address."},"404":{"description":"No visits from that address."}}}},"/visits/export":{"get":{"summary":"Every counted visit as CSV, one row per visit per document read — the file the settings page offers.","operationId":"get-visits-export","tags":["Views and visitors"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"from","in":"query","required":false,"description":"Visits from this moment.","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"description":"Visits up to this moment. A bare date covers the whole of that day.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"A CSV file."}}}},"/analytics/summary":{"get":{"summary":"Views against the previous period, visitors, reading time, completion, the top documents, rooms, links and visitors, devices, and a per-day series.","operationId":"get-analytics-summary","tags":["Analytics"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"days","in":"query","required":false,"description":"7, 30 or 90. Defaults to 30. Anything else is a 400.","schema":{"type":"integer"}}],"responses":{"200":{"description":"{ data: { days, since, current, previous, series[], topDocuments[], topRooms[], topLinks[], topVisitors[], recent[], devices, anonymousShare } } — `series` has one entry per day, oldest first; `anonymousShare` is the share of views (0–100) with no address captured"}}}},"/analytics/documents/{id}":{"get":{"summary":"Where readers spent their attention in one document, section by section — per page for a PDF — including visits that arrived through a room.","operationId":"get-analytics-documents-by-id","tags":["Analytics"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"shareLinkId","in":"query","required":false,"description":"Only visits through one link.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: { documentId, title, kind, unit, views, measuredViews, totalMs, sections: [{ index, heading, words, seen, readers, totalMs, medianMs, msPerHundredWords, friction, stoppedHere, reached, reachedPct }] } } — `unit` is `section` or `page`; `seen` counts visits that dwelt on a section at all and `readers` those that read it; `friction` is pace against the document's own median, where 1 is typical"}}}},"/questions":{"get":{"summary":"Question threads, those waiting on you first. The two hundred most recently opened; a specific thread is always reachable by id.","operationId":"get-questions","tags":["Viewer questions"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"awaiting","in":"query","required":false,"description":"`true` for threads where the reader spoke last.","schema":{"type":"boolean"}},{"name":"documentId","in":"query","required":false,"schema":{"type":"string"}},{"name":"dataRoomId","in":"query","required":false,"schema":{"type":"string"}},{"name":"shareLinkId","in":"query","required":false,"schema":{"type":"string"}},{"name":"email","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Thread[] } — id, documentId, dataRoomId, shareLinkId, linkName, about (the document or room title), askedByEmail, awaitingOwner, createdAt, lastMessageAt, messages: [{ id, author, body, createdAt, delivered }], opening question first"}}}},"/questions/{id}":{"get":{"summary":"One thread, every turn in order.","operationId":"get-questions-by-id","tags":["Viewer questions"],"security":[{"bearerAuth":["views:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Thread }"}}}},"/questions/{id}/reply":{"post":{"summary":"Answer in the thread. Emailed to the asker when the link captured an address; `delivered` says whether it went.","operationId":"post-questions-by-id-reply","tags":["Viewer questions"],"security":[{"bearerAuth":["links:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","description":"Up to 5,000 characters."}},"required":["body"]}}}},"responses":{"200":{"description":"{ data: Thread, delivered: boolean } — the reply is kept in the thread whether or not the email went"},"422":{"description":"The reply could not be recorded; the message says why."}}}},"/requests":{"get":{"summary":"File requests, most recently changed first, with progress counts.","operationId":"get-requests","tags":["File requests"],"security":[{"bearerAuth":["requests:read"]}],"parameters":[],"responses":{"200":{"description":"{ data: Request[] } — id, slug, url, title, description, dataRoomId, folderId, requireEmail, dueAt, remindEveryDays, notifyOnUpload, active, closedAt, createdAt, updatedAt, counts{items, assignees, completed, uploads}. `url` is the open upload page; each assignee is mailed their own."}}},"post":{"summary":"Ask for files. Assignees are mailed their own link at once.","operationId":"post-requests","tags":["File requests"],"security":[{"bearerAuth":["requests:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"1–200 characters."},"description":{"type":"string","description":"Up to 5,000 characters."},"items":{"type":"array","items":{},"description":"What is wanted, up to 50. `required` defaults to true."},"dataRoomId":{"type":"string","description":"Room uploads are filed into."},"folderId":{"type":"string","description":"A folder in that room. Needs `dataRoomId`."},"dueAt":{"type":"string","format":"date-time"},"remindEveryDays":{"type":"integer","description":"Reminder cadence for whoever has not finished."},"requireEmail":{"type":"boolean","description":"Ask an anonymous uploader who they are. Defaults to true."},"notifyOnUpload":{"type":"boolean","description":"Email you when something arrives. Defaults to true."},"assignees":{"type":"array","items":{},"description":"Up to 50, each mailed their own link."}},"required":["title"]}}}},"responses":{"201":{"description":"201 { data: Request & { items[], assignees[], uploads[] } }"},"404":{"description":"No such room, or no such folder in it."},"422":{"description":"A `folderId` without a `dataRoomId`."}}}},"/requests/{id}":{"get":{"summary":"The request with its items, assignees and what has arrived.","operationId":"get-requests-by-id","tags":["File requests"],"security":[{"bearerAuth":["requests:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Request & { items: [{ id, name, description, required, position }], assignees: Assignee[], uploads: [{ id, itemId, assigneeId, uploaderEmail, uploaderName, filename, contentType, byteSize, sha256, documentId, uploadedAt }] } } — an upload is read as the document named by `documentId`; assignee tokens and storage URLs are never included"}}},"patch":{"summary":"Change any setting. `active: false` closes it, and the link says so instead of accepting files.","operationId":"patch-requests-by-id","tags":["File requests"],"security":[{"bearerAuth":["requests:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"…":{"type":"string","description":"`title`, `description`, `dueAt`, `remindEveryDays`, `requireEmail`, `notifyOnUpload` and `active`, all optional. The room, folder, items and assignees are fixed once a request exists."}},"required":[]}}}},"responses":{"200":{"description":"{ data: Request }"}}},"delete":{"summary":"Delete the request. Uploads stay: they are documents in the workspace now.","operationId":"delete-requests-by-id","tags":["File requests"],"security":[{"bearerAuth":["requests:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/requests/{id}/assignees":{"post":{"summary":"Add people and mail each their link. Idempotent per address: somebody already on the request has their name updated and is mailed again rather than added twice.","operationId":"post-requests-by-id-assignees","tags":["File requests"],"security":[{"bearerAuth":["requests:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"assignees":{"type":"array","items":{},"description":"1–50 people."}},"required":["assignees"]}}}},"responses":{"201":{"description":"201 { data: Assignee[] } — every assignee on the request: id, email, name, delivery, deliveryError, sentAt, remindedAt, reminderCount, uploadedAt, completedAt, createdAt"}}}},"/requests/{id}/assignees/{assigneeId}":{"delete":{"summary":"Remove somebody. Their link stops working; what they already sent stays. Idempotent.","operationId":"delete-requests-by-id-assignees-by-assigneeId","tags":["File requests"],"security":[{"bearerAuth":["requests:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"assigneeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/requests/{id}/assignees/{assigneeId}/resend":{"post":{"summary":"Mail their link again — a fresh invitation if the first never arrived, otherwise a reminder.","operationId":"post-requests-by-id-assignees-by-assigneeId-resend","tags":["File requests"],"security":[{"bearerAuth":["requests:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"assigneeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Assignee, delivered: boolean }"},"404":{"description":"No such assignee on this request."}}}},"/hooks":{"get":{"summary":"Every webhook endpoint in the workspace, newest first — including those added on the settings page — and the catalogue of events.","operationId":"get-hooks","tags":["Webhooks"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[],"responses":{"200":{"description":"{ data: Hook[], events: [{ name, description }] } — `events` includes `ping`, the test event"}}},"post":{"summary":"Subscribe a URL. Re-subscribing the same URL to the same events returns the existing row rather than a duplicate, because platforms retry.","operationId":"post-hooks","tags":["Webhooks"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Must be https."},"events":{"type":"array","items":{},"description":"Event names, up to 50. Empty, with no `event` either, means every event."},"event":{"type":"string","description":"A single event, for platforms that subscribe one at a time. Merged with `events`."}},"required":["url"]}}}},"responses":{"201":{"description":"201 { data: Hook & { secret } } — the signing secret. An identical re-subscribe answers 200 with the existing row and its secret, and switches it back on if it had been switched off."},"422":{"description":"Unknown event names; `details.known` lists the valid ones."}}}},"/hooks/{id}":{"get":{"summary":"One subscription, with its recent health.","operationId":"get-hooks-by-id","tags":["Webhooks"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Hook } — id, url, events, active, failureCount, lastStatus, lastAttemptAt, createdAt. `failureCount` is consecutive failed deliveries; at 10 the endpoint is switched off."}}},"patch":{"summary":"Change the URL or events, or switch it on and off. Switching it on resets the failure count.","operationId":"patch-hooks-by-id","tags":["Webhooks"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Must be https."},"events":{"type":"array","items":{},"description":"Replaces the list. Empty means every event."},"active":{"type":"boolean"}},"required":[]}}}},"responses":{"200":{"description":"{ data: Hook }"},"422":{"description":"Unknown event names; `details.known` lists the valid ones."}}},"delete":{"summary":"Unsubscribe. Idempotent: a second call is a 204 too.","operationId":"delete-hooks-by-id","tags":["Webhooks"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content."}}}},"/hooks/{id}/ping":{"post":{"summary":"Send a `ping` delivery now, whatever the endpoint subscribes to and even if it is switched off, and report how it answered.","operationId":"post-hooks-by-id-ping","tags":["Webhooks"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Delivery & { payload } } — status, responseStatus, attempts, error"},"422":{"description":"The test delivery could not be recorded."}}}},"/hooks/{id}/rotate":{"post":{"summary":"Replace the signing secret. The new one is returned once.","operationId":"post-hooks-by-id-rotate","tags":["Webhooks"],"security":[{"bearerAuth":["documents:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Hook & { secret } }"}}}},"/hooks/{id}/deliveries":{"get":{"summary":"Every delivery attempt, newest first — which is how a webhook that “does not work” turns out to be one specific 401.","operationId":"get-hooks-by-id-deliveries","tags":["Webhooks"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"event","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"`pending`, `delivered` or `failed`. Anything else is a 400.","schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"`payload` adds the body that was sent.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Rows per page, up to 100. Defaults to 50.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Delivery[], nextCursor } — id, endpointId, event, status, attempts, responseStatus, error, deliveredAt, createdAt, payload?"}}}},"/hooks/samples":{"get":{"summary":"Recent real payloads for one event, for a platform's “load sample” step. A synthetic one of the same shape when nothing has happened yet.","operationId":"get-hooks-samples","tags":["Webhooks"],"security":[{"bearerAuth":["documents:read"]}],"parameters":[{"name":"event","in":"query","required":true,"description":"The event name.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: object[] } — up to three delivered bodies, each `{ id, event, createdAt, data }`"},"422":{"description":"Unknown event name; `details.known` lists the valid ones."}}}},"/audit":{"get":{"summary":"The trail, newest first.","operationId":"get-audit","tags":["Audit log"],"security":[{"bearerAuth":["audit:read"]}],"parameters":[{"name":"family","in":"query","required":false,"description":"`signing`, `sharing` or `documents`. Anything else is a 400.","schema":{"type":"string"}},{"name":"type","in":"query","required":false,"description":"One event type, e.g. `recipient.signed` — see GET /audit/types. An unknown one is a 400.","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"description":"Matches the description, actor name or actor email.","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"documentId","in":"query","required":false,"schema":{"type":"string"}},{"name":"envelopeId","in":"query","required":false,"schema":{"type":"string"}},{"name":"shareLinkId","in":"query","required":false,"description":"One link's history, including after the link was deleted.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Up to 500. Defaults to 100, or 500 with `format=csv`.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The previous page's `nextCursor`. Opaque — pass it back unchanged.","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"`csv` returns the same rows as a file.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ data: Event[], nextCursor } — id, type, family, description, actorName, actorEmail, envelopeId, documentId, recipientId, shareLinkId, subject{kind,id,title} (kind is envelope, document, room or link), ipAddress, userAgent, metadata, createdAt"},"400":{"description":"An unknown family or type, a date that does not parse, or a cursor that is not valid."}}}},"/audit/types":{"get":{"summary":"Every event type the log can hold, grouped by family, for building a filter.","operationId":"get-audit-types","tags":["Audit log"],"security":[{"bearerAuth":["audit:read"]}],"parameters":[],"responses":{"200":{"description":"{ data: { families: [{ id, label }], types: [{ type, family }] } }"}}}}},"x-webhooks":[{"name":"envelope.sent","description":"A document went out for signature."},{"name":"recipient.notified","description":"A signing email left for a recipient."},{"name":"recipient.bounced","description":"A signing email could not be delivered."},{"name":"recipient.viewed","description":"A recipient opened their signing page."},{"name":"recipient.authenticated","description":"A recipient passed the access code."},{"name":"recipient.signed","description":"A recipient completed their fields."},{"name":"recipient.declined","description":"A recipient declined to sign, with a reason."},{"name":"recipient.delegated","description":"A recipient reassigned signing to someone else."},{"name":"recipient.attached","description":"A recipient returned a file."},{"name":"envelope.reminded","description":"Reminders went to whoever is holding things up."},{"name":"envelope.completed","description":"Every signer has signed; the PDF is final."},{"name":"envelope.voided","description":"The sender cancelled the envelope."},{"name":"envelope.expired","description":"The envelope passed its expiry unsigned."},{"name":"consent.accepted","description":"A signer agreed to sign electronically."},{"name":"consent.withdrawn","description":"A signer withdrew that consent."},{"name":"document.created","description":"A new document was created."},{"name":"document.edited","description":"A document's body changed."},{"name":"document.redacted","description":"Text was permanently removed from a document."},{"name":"link.created","description":"A tracked link was published."},{"name":"link.updated","description":"A link's gates or settings changed."},{"name":"link.enabled","description":"A link was switched back on."},{"name":"link.disabled","description":"A link was switched off."},{"name":"link.deleted","description":"A link was removed."},{"name":"link.viewed","description":"A visitor cleared every gate and opened the link."},{"name":"link.nda_accepted","description":"A visitor accepted the link's confidentiality terms."},{"name":"link.downloaded","description":"A visitor downloaded a PDF copy."},{"name":"link.bulk_downloaded","description":"A visitor downloaded a room or folder as a zip."}]}