--- title: Document Command API --- ## Execute Commands on Documents **Required scope:** `public-api:write` Execute a Document Command based on its `id`. All commands run in a single transaction. **History** | Version | Change | | ------- | ------ | | release-2026-03 | Added `preserveUpdatedAt` parameter. When set to `true`, the document's `updated_at` timestamp is not modified. This is useful for imports and migrations where the original timestamps should be preserved. | | release-2025-07 | The following commands got added: `setEmbargo`, `removeEmbargo`, `addPublishSchedule`, `cancelPublishSchedule`, `addUnpublishSchedule`, `cancelUnpublishSchedule`. | | release-2024-11 | The following commands got added: `setComponentCondition`, `setComponentStyle`, `setIncludeDirective`, `setLinkDirective`, `setStyleDirective`. | | release-2024-07 | The following commands got added: `removeComponent`, `unpublish`. | | release-2024-05 | The following commands got added: `insertComponent`. | | release-2024-03 | A new `precondition` named `isPublishedAndHasNoChanges` has been added. | | release-2023-11 | Initial support. | **Curl Example** ```bash ACCESS_TOKEN=ey1234 curl -k -X PATCH "https://server.livingdocs.io/api/2026-05/documents/{documentId}/commands" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ --data-binary @- << EOF { "commands": [{ "operation": "setMetadataProperty", "propertyName": "title", "value": "updated title" }] } EOF ``` **Endpoint** ```http PATCH /api/2026-05/documents/{documentId}/commands ``` **Parameters** | Name | Type | Required | Notes | | ---- | ---- | :------: | ----- | | version | integer | | Current document version. When set on update the version is checked. | | preserveUpdatedAt | boolean | | When set to `true`, the document's `updated_at` timestamp is not modified by the command execution. By default (`false`), `updated_at` is set to the current time.

When combined with a `publish` command, the `lastPublicationDate` will also be set to the preserved `updated_at` timestamp instead of the current time.

This is useful for imports and migrations where the original timestamps should be preserved to maintain correct dashboard sort order. | | preconditions | array | | An array of preconditions for command execution. If a precondition assertion fails, no commands are executed and the request responds with a `429 Conflict` status.

Each entry is an object with at least a **type** property.

Possible types:
- `isPublished`: Document is currently public
- `isPublishedAndHasNoChanges`: Document is currently public and has no changes since last publish

See further details in example requests. | | commands | array | x | An array of commands to execute. Each entry is an object with at least an **operation** property.

Command API operations `publish`, `unpublish`, and `addPublishSchedule` can only be used as the last operation in a request and are mutually exclusive.

Possible operations:
- `setMetadataProperty`
- `setTitle`
- `insertComponent` Added in: [`release-2024-05`](/operations/releases/release-2024-05/)
- `removeComponent` Added in: [`release-2024-07`](/operations/releases/release-2024-07/)
- `setComponentCondition` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setComponentStyle` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setEditableDirective`
- `setIncludeDirective` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setLinkDirective` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setStyleDirective` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setEmbargo` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `removeEmbargo` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `addPublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `cancelPublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `addUnpublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `cancelUnpublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `publish`
- `unpublish` Added in: [`release-2024-07`](/operations/releases/release-2024-07/)

Some commands supports an optional `oldValue` parameter. When specified, the system verifies that the value being updated matches the provided `oldValue`. This prevents accidental overwrites that might occur due to changes made between reading a document and issuing the command. If the `oldValue` does not match, a conflict error is thrown. `oldValue` is redundant when providing a document version.

See further details in example requests. | **Example Request** ```js { "version": 1, // When true, the document's updated_at timestamp is preserved "preserveUpdatedAt": true, "preconditions": [ // Asserts that the document is published or // unpublished based on the value property. {"type": "isPublished", "value": true} // Asserts that the document is published and // has no changes since last publish. // {"type": "isPublishedAndHasNoChanges"} ], "commands": [ { // Update a single metadata property. "operation": "setMetadataProperty", "propertyName": "title", "value": "updated title", // send null to delete metadata property "oldValue": "previous title" // optional, for conflict detection (not necessary when sending document version too) }, { // Sets the title property on a document (might be overruled by displayTitlePattern on read). "operation": "setTitle", "value": "updated title", "oldValue": "previous title" }, { // Inserts a new component into the document content. "operation": "insertComponent", "componentId": "doc-custom-123456", "componentName": "paragraph", "content": { "text": "Some text" }, "position": { "parentComponentId": "doc-4a2b3g4d5", // Omit to insert into document root "parentContainerName": "children", // Omit to insert into document root, "previousComponentId": "doc-1a2b3c4d5", // To insert after component with this id "nextComponentId": "doc-1a2b3c4d5", // To insert before component with this id } }, { // Removes a component from the document content. // Does not work if component or parent component has `position: 'fixed'` "operation": "removeComponent", "componentId": "doc-4a2b3g4d5" }, { // Updates a component condition. Currently, only "dateTime" conditions // are supported. "operation": "setComponentCondition", "componentId": "doc-123", "conditionName": "dateTime", "value": { "gte": "2025-01-01T10:30:00.000Z", "lt": "2025-02-02T14:30:00.000Z" }, "oldValue": { "gte": "2024-01-01T10:30:00.000Z", "lt": "2024-02-02T14:30:00.000Z" } }, { // Updates a component style. It supports all types: style, option, and select. "operation": "setComponentStyle", "componentId": "doc-123", "propertyName": "background", "value": "#1fc47a", "oldValue": "#000" }, { // Sets the content of an editable directive. "operation": "setEditableDirective", "componentId": "doc-1a2b3c4d5", "directiveName": "headline", "value": "updated headline" }, { // Updates params and overrides of an include directive. These properties // depend on each other: if only params are provided, any existing // overrides are removed. Conversely, specifying overrides without params // is invalid and will return a validation error. To update overrides, // both the params and overrides properties must be provided. "operation": "setIncludeDirective", "componentId": "doc-123", "directiveName": "related-article", "value": { "params": { "teaser": { "$ref": "document", "reference": {"id": "3"} } }, "overrides": [{ "id": "teaser-normal-3", "content": { "link": {"href": "https://livingdocs.io"}, "title": "Changed title" }, "originalSnapshot": {}, "contentProperties": [] }] }, "oldValue": null }, { // Updates a link directive. "operation": "setLinkDirective", "componentId": "doc-123", "directiveName": "link", "value": { "href": "https://livingdocs.io/article/123", "target": "_blank", "$ref": "document", "reference": {"id": "123"} }, "oldValue": { "href": "https://livingdocs.io/" } }, { // Updates a style directive. It supports all types: style, option, and select. "operation": "setStyleDirective", "componentId": "doc-123", "directiveName": "appearance", "propertyName": "background", "value": "#1fc47a", "oldValue": "#000" }, { // Adds an embargo "operation": "setEmbargo", "reason": "Some reason", // optional "until": "2021-11-04T00:00:00Z" // optional }, { // Removes an embargo "operation": "removeEmbargo" }, { // Adds a publish schedule. Can only be the last command in a request. // Therefore, it cannot be used with "publish" or "unpublish". "operation": "addPublishSchedule", "date": "2021-11-04T00:00:00Z" }, { // Removes a publish schedule "operation": "cancelPublishSchedule" }, { // Adds a unpublish schedule "operation": 'addUnpublishSchedule', "date": "2021-11-04T00:00:00Z" }, { // Removes a unpublish schedule "operation": "cancelUnpublishSchedule" } { // Creates a new publication for the document if applicable. Can only // be the last command in a request. Therefore, it cannot be used with // "addPublishSchedule" or "unpublish". "operation": "publish" }, { // Unpublishes the document if it was published before. Can only be the // last command in a request. Therefore, it cannot be used with // "addPublishSchedule" or "publish". "operation": "unpublish" } ] } ``` **Response** _204 OK_ — `/api/2026-05/documents/{documentId}/commands` ```txt No Content ``` _400 Bad Request_ — `/api/2026-05/documents/{documentId}/commands` ```json { "status": 400, "error": "Bad Request", "error_details": { "commands.0": "value of tag \"operation\" must be in oneOf" } } // or { "status": 400, "error": "Bad Request", "error_details": { "commands.0.value": "must match exactly one schema in oneOf", "commands.0.value.params": "Missing required property: params" } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Metadata property \"notExistingProperty\" does not exist", "commandIndex": 0 } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Component 'doc-123' does not exist in document '123'", "commandIndex": 0 } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Directive 'my-directive' of type 'editable' does not exist on component 'doc-123' in document '123'", "commandIndex": 0 } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Include validation failed: {\"title\":\"Invalid type: expected string\",\"teasers.limit\":\"Missing required property: limit\",\"teasers.invalid\":\"Additional properties not allowed\"}", "commandIndex": 0 } } ``` _404 Not Found_ — `/api/2026-05/documents/{documentId}/commands` ```json { "status": 404, "error": "Not Found", "error_details": { "name": "NotFound", "message": "Document Not Found" } } ``` _409 Conflict_ — `/api/2026-05/documents/{documentId}/commands` ```json { "status": 409, "error": "Conflict", "error_details": { "name": "Conflict", "message": "The document you tried to update is outdated", "expectedVersion": 1, "currentVersion": 2 } } // or { "status": 409, "error": "Conflict", "error_details": { "name": "Conflict", "message": "Precondition failed: 'isPublished'" } } // or { "status": 409, "error": "Conflict", "error_details": { "name": "Conflict", "message": "Cannot update outdated value'" } } ``` ## Execute Commands on Documents > [!NOTE] > This endpoint has changes in version 2026-03. > **Required scope:** `public-api:write` Execute a Document Command based on its `id`. All commands run in a single transaction. **History** | Version | Change | | ------- | ------ | | release-2025-07 | The following commands got added: `setEmbargo`, `removeEmbargo`, `addPublishSchedule`, `cancelPublishSchedule`, `addUnpublishSchedule`, `cancelUnpublishSchedule`. | | release-2024-11 | The following commands got added: `setComponentCondition`, `setComponentStyle`, `setIncludeDirective`, `setLinkDirective`, `setStyleDirective`. | | release-2024-07 | The following commands got added: `removeComponent`, `unpublish`. | | release-2024-05 | The following commands got added: `insertComponent`. | | release-2024-03 | A new `precondition` named `isPublishedAndHasNoChanges` has been added. | | release-2023-11 | Initial support. | **Curl Example** ```bash ACCESS_TOKEN=ey1234 curl -k -X PATCH "https://server.livingdocs.io/api/2026-01/documents/{documentId}/commands" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ --data-binary @- << EOF { "commands": [{ "operation": "setMetadataProperty", "propertyName": "title", "value": "updated title" }] } EOF ``` **Endpoint** ```http PATCH /api/2026-01/documents/{documentId}/commands ``` **Parameters** | Name | Type | Required | Notes | | ---- | ---- | :------: | ----- | | version | integer | | Current document version. When set on update the version is checked. | | preconditions | array | | An array of preconditions for command execution. If a precondition assertion fails, no commands are executed and the request responds with a `429 Conflict` status.

Each entry is an object with at least a **type** property.

Possible types:
- `isPublished`: Document is currently public
- `isPublishedAndHasNoChanges`: Document is currently public and has no changes since last publish

See further details in example requests. | | commands | array | x | An array of commands to execute. Each entry is an object with at least an **operation** property.

Command API operations `publish`, `unpublish`, and `addPublishSchedule` can only be used as the last operation in a request and are mutually exclusive.

Possible operations:
- `setMetadataProperty`
- `setTitle`
- `insertComponent` Added in: [`release-2024-05`](/operations/releases/release-2024-05/)
- `removeComponent` Added in: [`release-2024-07`](/operations/releases/release-2024-07/)
- `setComponentCondition` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setComponentStyle` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setEditableDirective`
- `setIncludeDirective` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setLinkDirective` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setStyleDirective` Added in: [`release-2024-11`](/operations/releases/release-2024-11/)
- `setEmbargo` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `removeEmbargo` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `addPublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `cancelPublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `addUnpublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `cancelUnpublishSchedule` Added in: [`release-2025-07`](/operations/releases/release-2025-07/)
- `publish`
- `unpublish` Added in: [`release-2024-07`](/operations/releases/release-2024-07/)

Some commands supports an optional `oldValue` parameter. When specified, the system verifies that the value being updated matches the provided `oldValue`. This prevents accidental overwrites that might occur due to changes made between reading a document and issuing the command. If the `oldValue` does not match, a conflict error is thrown. `oldValue` is redundant when providing a document version.

See further details in example requests. | **Example Request** ```js { "version": 1, "preconditions": [ // Asserts that the document is published or // unpublished based on the value property. {"type": "isPublished", "value": true} // Asserts that the document is published and // has no changes since last publish. // {"type": "isPublishedAndHasNoChanges"} ], "commands": [ { // Update a single metadata property. "operation": "setMetadataProperty", "propertyName": "title", "value": "updated title", // send null to delete metadata property "oldValue": "previous title" // optional, for conflict detection (not necessary when sending document version too) }, { // Sets the title property on a document (might be overruled by displayTitlePattern on read). "operation": "setTitle", "value": "updated title", "oldValue": "previous title" }, { // Inserts a new component into the document content. "operation": "insertComponent", "componentId": "doc-custom-123456", "componentName": "paragraph", "content": { "text": "Some text" }, "position": { "parentComponentId": "doc-4a2b3g4d5", // Omit to insert into document root "parentContainerName": "children", // Omit to insert into document root, "previousComponentId": "doc-1a2b3c4d5", // To insert after component with this id "nextComponentId": "doc-1a2b3c4d5", // To insert before component with this id } }, { // Removes a component from the document content. // Does not work if component or parent component has `position: 'fixed'` "operation": "removeComponent", "componentId": "doc-4a2b3g4d5" }, { // Updates a component condition. Currently, only "dateTime" conditions // are supported. "operation": "setComponentCondition", "componentId": "doc-123", "conditionName": "dateTime", "value": { "gte": "2025-01-01T10:30:00.000Z", "lt": "2025-02-02T14:30:00.000Z" }, "oldValue": { "gte": "2024-01-01T10:30:00.000Z", "lt": "2024-02-02T14:30:00.000Z" } }, { // Updates a component style. It supports all types: style, option, and select. "operation": "setComponentStyle", "componentId": "doc-123", "propertyName": "background", "value": "#1fc47a", "oldValue": "#000" }, { // Sets the content of an editable directive. "operation": "setEditableDirective", "componentId": "doc-1a2b3c4d5", "directiveName": "headline", "value": "updated headline" }, { // Updates params and overrides of an include directive. These properties // depend on each other: if only params are provided, any existing // overrides are removed. Conversely, specifying overrides without params // is invalid and will return a validation error. To update overrides, // both the params and overrides properties must be provided. "operation": "setIncludeDirective", "componentId": "doc-123", "directiveName": "related-article", "value": { "params": { "teaser": { "$ref": "document", "reference": {"id": "3"} } }, "overrides": [{ "id": "teaser-normal-3", "content": { "link": {"href": "https://livingdocs.io"}, "title": "Changed title" }, "originalSnapshot": {}, "contentProperties": [] }] }, "oldValue": null }, { // Updates a link directive. "operation": "setLinkDirective", "componentId": "doc-123", "directiveName": "link", "value": { "href": "https://livingdocs.io/article/123", "target": "_blank", "$ref": "document", "reference": {"id": "123"} }, "oldValue": { "href": "https://livingdocs.io/" } }, { // Updates a style directive. It supports all types: style, option, and select. "operation": "setStyleDirective", "componentId": "doc-123", "directiveName": "appearance", "propertyName": "background", "value": "#1fc47a", "oldValue": "#000" }, { // Adds an embargo "operation": "setEmbargo", "reason": "Some reason", // optional "until": "2021-11-04T00:00:00Z" // optional }, { // Removes an embargo "operation": "removeEmbargo" }, { // Adds a publish schedule. Can only be the last command in a request. // Therefore, it cannot be used with "publish" or "unpublish". "operation": "addPublishSchedule", "date": "2021-11-04T00:00:00Z" }, { // Removes a publish schedule "operation": "cancelPublishSchedule" }, { // Adds a unpublish schedule "operation": 'addUnpublishSchedule', "date": "2021-11-04T00:00:00Z" }, { // Removes a unpublish schedule "operation": "cancelUnpublishSchedule" } { // Creates a new publication for the document if applicable. Can only // be the last command in a request. Therefore, it cannot be used with // "addPublishSchedule" or "unpublish". "operation": "publish" }, { // Unpublishes the document if it was published before. Can only be the // last command in a request. Therefore, it cannot be used with // "addPublishSchedule" or "publish". "operation": "unpublish" } ] } ``` **Response** _204 OK_ — `/api/2026-01/documents/{documentId}/commands` ```txt No Content ``` _400 Bad Request_ — `/api/2026-01/documents/{documentId}/commands` ```json { "status": 400, "error": "Bad Request", "error_details": { "commands.0": "value of tag \"operation\" must be in oneOf" } } // or { "status": 400, "error": "Bad Request", "error_details": { "commands.0.value": "must match exactly one schema in oneOf", "commands.0.value.params": "Missing required property: params" } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Metadata property \"notExistingProperty\" does not exist", "commandIndex": 0 } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Component 'doc-123' does not exist in document '123'", "commandIndex": 0 } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Directive 'my-directive' of type 'editable' does not exist on component 'doc-123' in document '123'", "commandIndex": 0 } } // or { "status": 400, "error": "Bad Request", "error_details": { "message": "Command at index 0 failed: Include validation failed: {\"title\":\"Invalid type: expected string\",\"teasers.limit\":\"Missing required property: limit\",\"teasers.invalid\":\"Additional properties not allowed\"}", "commandIndex": 0 } } ``` _404 Not Found_ — `/api/2026-01/documents/{documentId}/commands` ```json { "status": 404, "error": "Not Found", "error_details": { "name": "NotFound", "message": "Document Not Found" } } ``` _409 Conflict_ — `/api/2026-01/documents/{documentId}/commands` ```json { "status": 409, "error": "Conflict", "error_details": { "name": "Conflict", "message": "The document you tried to update is outdated", "expectedVersion": 1, "currentVersion": 2 } } // or { "status": 409, "error": "Conflict", "error_details": { "name": "Conflict", "message": "Precondition failed: 'isPublished'" } } // or { "status": 409, "error": "Conflict", "error_details": { "name": "Conflict", "message": "Cannot update outdated value'" } } ```