API reference

Legal hold and retention API

Legal holds and retention rules, for the records team. While a hold is active nothing it covers can be moved to the trash or deleted for good, by anyone, through any door; retention rules purge what has passed its time.

Base URL https://xdocs.io/api/v1, with Authorization: Bearer xdk_… on every request. Pagination, rate limits, scopes and error codes are the same for every endpoint and are described once, in how the API behaves.

Compliance

Legal holds and retention rules. While a hold is active, nothing it covers can be moved to the trash or deleted for good — through the app, the assistant, this API or a retention rule; DELETE on a held document, room or folder answers 409. A keep rule is a floor (not deleted for good before its period ends) and a trash rule a ceiling (the nightly sweep moves documents to the trash once that old). Releasing a hold ends a preservation order and is done by an admin in Settings → Compliance, not through the API.

POST/api/v1/legal-holdscompliance:write

Place a legal hold. Everything its scopes cover now is recorded against it at once; a document filed into a held folder or room later is covered immediately and recorded overnight, and stays held if it is moved out. Audited, and sent as the legal_hold.placed webhook.

Body (JSON)

namestringrequired
The matter, up to 200 characters.
reasonstring
The matter number, the order, who asked. Up to 2,000 characters.
scopes{kind, targetId?}[]required
1–50. kind is workspace, folder (with everything under it), room, document or custodian; targetId is the folder, room or document id, or for a custodian the email address of the person whose documents are held. Omit it for workspace.

Returns

201 { data: { id, name, reason, status, scopes: [{ id, kind, targetId }], documents, placedBy, createdAt, releasedAt, releasedBy, releaseNote } }

  • 404 A folder, room or document that is not this workspace's.
  • 422 No name, no scope, or a scope without its target.
POST/api/v1/legal-holds/:id/scopescompliance:write

Widen an active hold to cover more. Sending a scope it already has records what it covers again and changes nothing else.

Body (JSON)

kindstringrequired
workspace, folder, room, document or custodian.
targetIdstring
As on POST /legal-holds.

Returns

201 { data: { id, name, reason, status, scopes: [{ id, kind, targetId }], documents, placedBy, createdAt, releasedAt, releasedBy, releaseNote } }

  • 404 No such hold, or a target that is not this workspace's.
  • 422 The hold has been released.
GET/api/v1/retention-rulescompliance:read

Every retention rule, oldest first, with when the nightly sweep last applied it.

Returns

{ data: [{ id, name, action, periodDays, basis, scope, scopeId, documentKind, enabled, createdAt, updatedAt, lastRunAt, lastRunTrashed }] }

POST/api/v1/retention-rulescompliance:write

Add a retention rule. Where rules overlap, the longest keep and the shortest trash win, a longer keep stops a trash rule acting, a hold beats every rule, and a signed document is never deleted.

Body (JSON)

namestringrequired
Up to 200 characters.
actionstringrequired
keep (not deleted for good before the period ends) or trash (moved to the trash once that old).
periodDaysintegerrequired
1–36,500.
basisstring
What the period counts from: created (default), updated or completed (signing; never applies to an unsigned document).
scopestring
workspace (default), folder (with everything under it) or room.
scopeIdstring
The folder or room id, for those scopes.
documentKindstring
Only xdoc, sheet, pdf or file documents. All kinds when absent.
enabledboolean
Defaults to true.

Returns

201 { data: { id, name, action, periodDays, basis, scope, scopeId, documentKind, enabled, createdAt, updatedAt, lastRunAt, lastRunTrashed } }

  • 404 A folder or room that is not this workspace's.
  • 422 No name, or a period outside 1–36,500 days.
PATCH/api/v1/retention-rules/:idcompliance:write

Change a rule, or turn it off with enabled: false. Fields left out are kept.

Body (JSON)

namestring
As on POST.
actionstring
As on POST.
periodDaysinteger
As on POST.
basisstring
As on POST.
scopestring
As on POST.
scopeIdstring
As on POST.
documentKindstring
As on POST; null for all kinds.
enabledboolean
Off keeps the rule without applying it.

Returns

{ data: { id, name, action, periodDays, basis, scope, scopeId, documentKind, enabled, createdAt, updatedAt, lastRunAt, lastRunTrashed } }

  • 404 No such rule in this workspace.
  • 422 As on POST.
DELETE/api/v1/retention-rules/:idcompliance:write

Delete a rule. Documents it already moved to the trash stay there.

Returns

204

  • 404 No such rule in this workspace.
← The whole API referenceNext: Audit log API →