CMI
primedocs integrates with CMI in several ways. Which variant fits depends on where the document creation process starts and which clients are in use:
| Variant | Process starts in | Building blocks |
|---|---|---|
| A — Connect (desktop to desktop) | CMI Desktop | Connect via console call |
| B — Web to web | CMI Web | Connect Session Template |
| C — CMI as data source and storage target | primedocs | HttpDataProvider (Select) and Output Management |
The URLs in the examples (cmi.example.com) are placeholders — the effective hosts and paths (including the tenant) are installation-specific and provided by CMI. The examples show the key elements of the configuration; schemas, fields, and mappings need to be adapted to the concrete use case.
Prerequisites for variants B and C
The CMI REST APIs require OAuth 2.0 authentication. Both are prepared in the DataSource Admin:
- Connected Service for CMI: Create a Connected Service under Settings → Connected Services (key
CMIin the examples). All configurations reference it viaConnectedServiceKeyand insert the access token via the placeholder{__ConnectedService.AccessToken__}(typically in theAuthorizationheader). - URL allow-list for
InvokeUrl: Allow the CMI target URLs used for upload and storage (variants B and C) under Settings → Connect Settings → InvokeUrl - Configuration. Without this entry, theInvokeUrlcall is blocked.
Variant A — Connect (desktop to desktop)
In a pure desktop environment, CMI Desktop invokes the primedocs desktop client automatically in the background and passes a Connect file containing the data of the business case (e.g. recipients, subject, references). From the user's point of view this is a single action in CMI — with no manual intermediate step.
Technically, CMI issues the console call of the primedocs client (not run by hand):
.\primedocs.exe /connect "C:\Temp\Geschaeft-1234.pdcx"
primedocs creates the document from it; storing the result in CMI is handled by CMI itself. Details on the invocation mechanism (file extensions, protocol handler, fetching the Connect XML from a URL): Start document generation.
Variant B — Web to web (Connect Session Template)
CMI Web embeds primedocs web (iframe or new tab) and starts a pre-initialized document creation via the URL of a Connect Session Template:
https://{instance}/app/web/session/template/cmi?saveLocationCmiTenant={tenant}&saveLocationCmiToken={token}&document={document-guid}
The parameter names can be chosen freely — they only need to match what the session template consumes via $.parameter(…). In this example, CMI passes:
| Parameter | Purpose |
|---|---|
saveLocationCmiTenant | CMI tenant used for storing the result. |
saveLocationCmiToken | Token of the CMI document under which the result is stored. |
document | GUID of the CMI document — used by the initializer to load the business case data. |
The flow:
- When the session starts, the initializers load data from CMI (
HttpDataProvider→ CMI ContentProvider API) and pick up the storage parameters (CodeDataProvider). - The user selects the template, fills in the form, and generates the document.
- The
OnSuccesscommands upload the document to CMI (InvokeUrl), confirm the storage (ShowDialog), and report completion to the embedding CMI (BrowserParentPostMessage) so CMI can continue its process.
Connect Session Template
<ConnectSessionTemplatesConfiguration>
<ConnectSessionTemplate Name="cmi">
<Initializers>
<!-- Loads data of the CMI document via the ContentProvider API -->
<HttpDataProvider ConnectedServiceKey="CMI">
<Configuration>
<Step>
<Request Method="POST">
<Url><![CDATA[https://cmi.example.com/{tenant}/v2/ContentProvider]]></Url>
<Header Name="Authorization" Value="Bearer {__ConnectedService.AccessToken__}" />
<Header Name="Content-Type" Value="application/json" />
<BodyBuilder><![CDATA[
function main() {
return JSON.stringify({
dokumentGuid: $.parameter("document"),
contentProviderKeys: [ "Kontakte" ]
});
}
]]></BodyBuilder>
</Request>
<Response>
<Data JsonPath="$.Kontakte[*]">
<Code>
function main() {
return {
Forms: {
Kontakte: {
"Key": source("name"),
"Name": source("displayName")
}
}
};
}
</Code>
</Data>
</Response>
</Step>
</Configuration>
</HttpDataProvider>
<!-- Picks up the CMI storage location from the URL parameters -->
<CodeDataProvider>
<Code><![CDATA[
function main() {
return {
Data: {
"CmiTenant": $.parameter("saveLocationCmiTenant"),
"CmiToken": $.parameter("saveLocationCmiToken")
}
};
}
]]></Code>
</CodeDataProvider>
</Initializers>
<Commands>
<OnSuccess>
<!-- Uploads the generated document to CMI -->
<InvokeUrl ConnectedServiceKey="CMI">
<Step>
<MultipartFormDataRequest>
<Url field-Content="Fields.UploadUrl" />
<Header Name="Authorization" Value="Bearer {__ConnectedService.AccessToken__}" />
<Header Name="Accept" Value="application/json" />
<File Name="file" field-FileName="Fields.FileName">
<Document />
</File>
</MultipartFormDataRequest>
</Step>
</InvokeUrl>
<ShowDialog Title="CMI" Message="The document has been stored in CMI." />
<!-- Notifies the embedding CMI about completion -->
<BrowserParentPostMessage TargetOrigin="https://cmi.example.com">
<Code><![CDATA[
function main() {
return {
type: "template-chooser-document-uploaded",
name: $("Fields.FileName")
};
}
]]></Code>
</BrowserParentPostMessage>
</OnSuccess>
</Commands>
</ConnectSessionTemplate>
</ConnectSessionTemplatesConfiguration>
The available contentProviderKeys and the field structure of the response are defined by CMI; the transformation into the Forms structure happens in the Code element via source(…).
Related document functions of the template
Data receives the storage parameters, Fields builds the upload URL from them, Forms defines the target structure for the loaded CMI data:
<DataConfiguration>
<Schema>
<Text Id="CmiTenant" />
<Text Id="CmiToken" />
</Schema>
</DataConfiguration>
<FieldsConfiguration>
<Fields>
<Text Name="UploadUrl">
<Code><![CDATA[
function main() {
return "https://cmi.example.com/" + $("Data.CmiTenant") + "/v1/Template/" + $("Data.CmiToken");
}
]]></Code>
</Text>
<Text Name="FileName" Value="Document.docx" />
</Fields>
</FieldsConfiguration>
<FormsConfiguration>
<Elements>
<ObjectCollection Id="Kontakte" Label="Kontakt" SelectedObjectId="Kontakt">
<Schema>
<Text Id="Key" Label="Key" />
<Text Id="Name" Label="Name" />
</Schema>
</ObjectCollection>
</Elements>
</FormsConfiguration>
Thanks to SelectedObjectId, the user's selection is available to fields and placeholders as Forms.Kontakt (e.g. $("Forms.Kontakt").Name), see Forms.
Word content controls following the naming scheme CMI_[FIELDNAME] as well as bookmarks are filled automatically by CMI when it processes the document further. This allows CMI metadata to be added without primedocs having to supply the data.
Up to primedocs 4.0, the CMI web integration was configured via the <cmi> element in primedocs.config and the fixed URL /app/web/cmi. The Connect Session Template approach supersedes that configuration: data retrieval, upload endpoint, authentication (Connected Service instead of a client secret in the configuration file), and the behaviour after generation are freely configurable.
Variant C — CMI as data source and storage target
This variant is interesting when the document is not created from within CMI — for example directly in primedocs web or in Office — but data of a CMI business case should still flow in and/or the result should be written back to CMI. The two building blocks can be used independently of each other.
Loading a business case from CMI (Select)
An Object in the Forms configuration gets an HttpDataProvider that calls the CMI search API. The user searches for the business case in the form; its values are then available to the template as Forms.Geschaeft.*.
<FormsConfiguration>
<Elements>
<Text Id="FileName" Label="Document name" Value="primedocs document" />
<Object Id="Geschaeft" Label="CMI business case">
<Schema>
<Text Id="Id" Label="Id" />
<Text Id="Titel" Label="Title" />
<Text Id="Typ" Label="Type" />
<Text Id="Status" Label="Status" />
<Text Id="Nummer" Label="Number" />
<Text Id="Beginn" Label="Start" />
</Schema>
<Summary>
<Field Id="Nummer" />
<Field Id="Titel" />
</Summary>
<DataProviders>
<HttpDataProvider DisplayName="CMI" ConnectedServiceKey="CMI">
<SearchParameters>
<Text Id="Term" Label="Search term" Required="true" />
</SearchParameters>
<Configuration>
<Step>
<Request Method="GET">
<UrlBuilder><![CDATA[
function main() {
const baseUrl = "https://cmi.example.com/api";
return baseUrl + "/AbstraktesGeschaeft/Search/FULLTEXT[" + $("Term") + "]";
}
]]></UrlBuilder>
<Header Name="Authorization" Value="Bearer {__ConnectedService.AccessToken__}" />
</Request>
<Response>
<Data JsonPath="$[*]">
<Mapping>
<Map Source="guid" Target="Id" />
<Map Source="typeName" Target="Typ" />
<Map Source="titel" Target="Titel" />
<Map Source="lifecycleStatus" Target="Status" />
<Map Source="laufnummer" Target="Nummer" />
<Map Source="beginn" Target="Beginn" />
</Mapping>
</Data>
</Response>
</Step>
</Configuration>
</HttpDataProvider>
</DataProviders>
</Object>
</Elements>
</FormsConfiguration>
Writing the document to CMI (Output Management)
A DesktopOutput in Output Management stores the document via the CMI API — in two steps: first the document object is created in the business case, then the generated file is checked in as a PDF.
The Fields configuration provides the file name and the request body:
<FieldsConfiguration>
<Fields>
<Text Name="FileName">
<Code><![CDATA[
function main() {
let fileName = $("Forms.FileName");
if (fileName == null) {
fileName = "Document";
}
if (!fileName.toLowerCase().endsWith(".pdf")) {
fileName += ".pdf";
}
return fileName;
}
]]></Code>
</Text>
<Text Name="CreateDocumentBody">
<Code><![CDATA[
function main() {
if ($("Forms.Geschaeft") == null) {
return "";
}
return JSON.stringify({
titel: $("Forms.FileName"),
version: 0,
bemerkung: "Generated via primedocs",
geschaeft: {
guid: $("Forms.Geschaeft").Id
}
});
}
]]></Code>
</Text>
</Fields>
</FieldsConfiguration>
The output executes both steps via an InvokeUrl command:
<OutputConfiguration>
<DesktopOutput Name="Store in CMI">
<Commands>
<InvokeUrl ConnectedServiceKey="CMI">
<!-- Step 1: create the document object in the CMI business case -->
<Step>
<Request Method="POST">
<Url>https://cmi.example.com/api/Dokument</Url>
<Header Name="Authorization" Value="Bearer {__ConnectedService.AccessToken__}" />
<Header Name="Content-Type" Value="application/json" />
<Body field-Content="Fields.CreateDocumentBody" />
</Request>
<Response>
<Property Name="DokumentGuid" JsonPath="$" />
</Response>
</Step>
<!-- Step 2: check in the generated file as PDF -->
<Step>
<MultipartFormDataRequest>
<Url>https://cmi.example.com/api/Dokument/CheckIn/{DokumentGuid}</Url>
<Header Name="Authorization" Value="Bearer {__ConnectedService.AccessToken__}" />
<Header Name="Accept" Value="application/json" />
<File Name="file" field-FileName="Fields.FileName" ContentType="application/pdf">
<Document Conversion="Pdf" />
</File>
</MultipartFormDataRequest>
</Step>
</InvokeUrl>
</Commands>
</DesktopOutput>
</OutputConfiguration>
For primedocs web and the Office web add-ins, the same storage can be configured as a WebOutput — InvokeUrl is one of the web-capable commands (see Output Management).
Related topics
- Connect Session Templates — named, pre-initialized Connect sessions
- Connected Services — authentication against external services on the user's behalf
- HttpDataProvider — retrieving data from HTTP/REST APIs (Select)
- Output Management — transferring the document to endpoints
- Connect Commands —
InvokeUrl,ShowDialog,BrowserParentPostMessage - Start document generation — console call and protocol handler