--- title: Kordiam Global Integration description: Integrate Kordiam with Livingdocs --- > [!NOTE] > Added in: [`release-2024-11`](/operations/releases/release-2024-11/). > Prior to [`release-2024-11`](/operations/releases/release-2024-11/), the Kordiam Global Integration was known as [Desk-Net Global Integration](/guides/integrations/desknet). > [!NOTE] > See the [Kordiam Platform Integration](/guides/integrations/kordiam-legacy/llms.txt) guide for details about the legacy integration used prior to [`release-2024-05`](/operations/releases/release-2024-05/), or read the [Kordiam Global Integration migration guide](/guides/integrations/kordiam-global-integration-migration/llms.txt) for details on upgrading from the platform integration to the global integration. ## Setup ### Kordiam The [Global Export Integration (Webhooks)](https://support.kordiam.io/hc/en-us/articles/5288027432860-Global-Export-Integration-Webhooks) feature must be enabled by Kordiam for your organisation before you can use it with Livingdocs. You will need to provide a URL and a token. The base URL should be `https:///api/2026-05/kordiam`. The token can be generated from the Api Clients page within the Project Admin section of the editor. The Kordiam integration scope must be selected (no other scope is necessary). ### Server config To setup the Livingdocs server the server config needs to be updated to enable Kordiam: ```js { integrations: { kordiam: { allowed: true, registerHooks: true, forceLinkUsingKordiamApiRequest: false } } } ``` If you use a proxy or message queue between Kordiam and Livingdocs you can define `forceLinkUsingKordiamApiRequest: true`. This sends an extra Kordiam API request to set the `externalId` on the Kordiam story after creating a Livingdocs document. It's also possible to prevent the hooks from being registered to reduce side effects while testing. > [!NOTE] > Please be aware that the global integration uses `integrations.kordiam`, and not `kordiam` which the legacy platform integration uses. ### Project config In the project config you will also need to enable the integration and configure the required `credentials`. For more information on how to use secrets, please check [Project Secrets](/guides/setup/project-secrets/llms.txt). The remainder of the config properties are used to reference the Kordiam functions required for your workflows. Along with the project-level config you will also need to register the [`li-kordiam-global`](/reference/document/metadata/plugins/li-kordiam-global/llms.txt) metadata plugin on each content type you would like to be able to link to a Kordiam story. The metadata plugin must be indexed. ```js { settings: { integrations: { kordiam: { enabled: true, credentials: { clientId: 'my-kordiam-client-id', clientSecret: { $secretRef: { name: 'my-kordiam-secret' } } }, createDocumentFunction: 'myCreateDocumentFunction', createElementFunction: 'myCreateElementFunction', incomingElementToDocumentCommandsFunction: 'myIncomingElementToDocumentCommandsFunction', outgoingDocumentToElementFunction: 'myOutgoingDocumentToElementFunction', outgoingDocumentToElementEventSources: ['publish', 'unpublish', 'update'] // Default: ['publish', 'unpublish'] } } }, contentTypes: [ { handle: 'myArticle', documentType: 'article', metadata: [ { handle: 'kordiamGlobal', // Any handle type: 'li-kordiam-global', config: {index: true} // Must be indexed } ] } ] } ``` > [!NOTE] > Please be aware that the global integration uses `settings.integrations.kordiam`, and not `settings.kordiam` which the legacy platform integration uses. ### Register functions Once your configs are setup you can register the Kordiam functions. All of the functions are optional, so you can simply configure the ones you need for your integration workflow. ```js liServer.registerInitializedHook(() => { if (liServer.features.isActive('li-kordiam')) { liServer.registerKordiamFunctions([ require('./app/kordiam-functions/create-document'), require('./app/kordiam-functions/create-element'), require('./app/kordiam-functions/incoming'), require('./app/kordiam-functions/outgoing') ]) } }) ``` #### `createDocumentFunction` The `createDocumentFunction` is called whenever an un-linked Kordiam story is created or updated. The `element` provided by Kordiam is forwarded to the function, along with the `userId` of the API client actor, the `projectConfig` of the current project, and the `kordiamApi`. For details of the values contained within the `element` please see the [Get Element](https://api.kordiam.app/#api-Element-GetElement) section of the Kordiam API documentation. If you wish to create a document the function should return an object with a `document` property containing document data. The `title` and `contentType` properties are required, and `content`, `designVersion`, `metadata`, `metadataSource`, and `translations` are all optional. If you do not need to create a document, for example when the Kordiam story status does not meet a certain condition, then do not return a value. ```js { handle: 'myCreateDocumentFunction', action ({userId, element, projectConfig, kordiamApi}) { return { document: { title: element.slug, // required contentType: 'regular', // required content: [{component: 'title', content: {text: 'My Title'}}], // designVersion: '1.0.0', metadata: {description: 'My description'}, // metadataSource: {}, // translations: [{locale: 'en', metadata: {}}] } } } } ``` #### `createElementFunction` The `createElementFunction` is used to create a Kordiam story from a Livingdocs document, and link the two together. When configured, a "Create Story" button will appear in the metadata form of any content type with the `li-kordiam-global` metadata plugin (when the document is not already linked to Kordiam). The function will be called with a `document` property, the `userId` of the user that triggered the request, the `projectConfig` of the current project, and the `kordiamApi`. The function should return an object containing an `element` property. Due to the constraints enforced by the Kordiam API the `element` object must contain at least one of the following: Publication platform, Task, Group. The Livingdocs code will handle setting the `externalElement` value and sending the request to Kordiam. For details of the values you can provide within the `element` please see the [Update Element](https://api.kordiam.app/#api-Element-UpdateElement) section of the Kordiam API documentation. If you do not want to create a Kordiam story for the specific document then the function can throw an error and the message will be displayed to the user. ```js { handle: 'myCreateElementFunction', action ({document, userId, projectConfig, kordiamApi}) { const dateParts = (new Date()).toISOString().split('T') const element = { slug: document.title, title: document.metadata.description, elementStatus: document.isPublished() ? 2 : 1, publications: [{ category: 123, single: { start: { date: dateParts[0], time: dateParts[1].slice(0, 5) } } }] } return {element} } } ``` #### `incomingElementToDocumentCommandsFunction` The `incomingElementToDocumentCommandsFunction` is called every time a linked Kordiam story is updated. It is called with the Livingdocs `document`, the `userId` of the API client actor, the `element` from Kordiam, the `projectConfig` of the current project, and the `kordiamApi`. For details of the values contained within the `element` please see the [Get Element](https://api.kordiam.app/#api-Element-GetElement) section of the Kordiam API documentation. The expected return value is an object with a `commands` array. The function can optionally return a `preconditions` array as well. For further details on what can be within the `commands` and `preconditions` arrays please see the [Document Command API](/reference/public-api/document-command-api/llms.txt) reference documentation. If no document update is necessary then the function should not return a value. ```js { handle: 'myIncomingElementToDocumentCommandsFunction', action ({document, userId, element, projectConfig, kordiamApi}) { return { commands: [{ operation: 'setMetadataProperty', propertyName: 'manualStatus', value: 'modified' }], preconditions: [{type: 'isPublishedAndHasNoChanges'}] } } } ``` #### `outgoingDocumentToElementFunction` The `outgoingDocumentToElementFunction` function is called after certain events within Livingdocs, and is used to synchronise Livingdocs document changes to Kordiam. It has an additional config option, `outgoingDocumentToElementEventSources`, which pre-filters when the function is called. The value of the property should be an array containing any of the following strings: `'publish'`, `'unpublish'`, `'update'`. By default the function will be called for publish and unpublish events. The function is called with the Livingdocs `document`, the `userId` of the user which updated the document, the Kordiam `elementId`, the `eventSource`, a metadata `changes` array, the `projectConfig` of the current project, and the `kordiamApi`. The `eventSource` will be `'publish'`, `'unpublish'`, or `'update'`. The `changes` array is only present for `'update'` events. Each change object in the array includes the `metadataProperty` handle, the `oldValue` and the `newValue`. If you would like to update the Kordiam story then you should load the latest element using `kordiamApi.getElement(elementId)`, apply any changes you would like to make to it, and then return an object with an `element` property. If you do not need to update the Kordiam story then do not return a value. ```js { handle: 'myOutgoingDocumentToElementFunction', async action ({document, userId, elementId, eventSource, changes, projectConfig, kordiamApi}) { const element = await kordiamApi.getElement(elementId) const elementStatus = document.isPublished() ? 2 : 1 if (elementStatus !== element.elementStatus) { return { element: {...element, elementStatus} } } } } ``` ## Story Planning Schedule in Livingdocs An optional step is to enable the story planning side panel within the Livingdocs editor. Further details can be found in the [Kordiam Schedule Guide](/guides/integrations/kordiam-schedule/llms.txt).