Connect API
Via the Connect API, third-party systems can use primedocs document generation on the server side via the primedocs Connect interface.
Endpoints
All Connect API endpoints live under …/api/v3/{datasourceId}/Connect. The request body is the primedocs Connect XML. The Connect API runs without a user context (client credentials). For scenarios with a user context and connected services, use the Connect Session API.
| Method | Endpoint | Purpose |
|---|---|---|
POST | /Document | Generates a document and returns the file. With the query parameter conversion=Pdf the result is returned as a PDF (default: None). |
POST | /Result | Runs the generation and returns a ConnectResultReport (JSON). The document itself is handled by a command (e.g. InvokeUrl). |
POST | /Update | Updates an existing primedocs document and returns the updated file. Supports conversion=Pdf. See Update a document. |
GET | /Templates | Lists the available templates (paged). |
POST | /Session | Creates a Connect Session and returns a ConnectSessionResult with a sessionId and a webAppLink to the web app. |
POST | /File | Deprecated. Use /Document instead. |
A Connect is validated internally when a session is created (POST /Session). There is no standalone /Validate endpoint in this API version.
The former /File endpoint remains for compatibility but redirects to /Document. New integrations should use /Document.
PDF output
POST …/Connect/Document?conversion=Pdf returns the generated document as a PDF. Without the parameter (or conversion=None), the native Office format is returned.
For server-side PDF generation:
- Images are embedded correctly: images from the profile and organization unit (e.g. logos or signatures) are included in the PDF.
- Date format follows the document language: data-bound date fields are formatted according to the document's language, not the server language (so, for example, no German month name in a French document).
Querying templates (/Templates)
GET …/Connect/Templates returns a paged list (query parameters page and pageSize with default 10, max 100). Optional filters:
userQuery: e.g.title:*Letter* field[FIELD.ID]:*value*templateQuery: e.g.templateId:GUID active:true tags:TAG1;TAG2 localizedName:*Letter*. The options are the same as in the Admin API.templateGroupIdalso finds the templates of the sub groups.uiLcid,userId: optional.
The meta template IDs usable in templateQuery are provided by the common endpoint GET .../Common/MetaTemplates. It can be called with the same Connect token (pd_ConnectWebApi). No additional client for the Admin API is needed.
The response contains only templates for which the target user holds the Use permission level, either directly or through one of their directory groups (see Template permissions). The permission filter is applied before paging: the total number of matches therefore also counts permitted templates only. Organization-unit permissions are additionally checked per profile, so the profiles returned for a template likewise contain approved entries only.
Only current template types are considered: Word content, Outlook email, Outlook signature, Outlook campaign, Excel and PowerPoint templates, and external documents. Legacy templates (“classic”) are excluded. The other query and permission filters apply unchanged.
Excluding legacy templates is new. A query using the meta template ID of a legacy type previously returned matches, but today the response stays empty. Adapt existing integrations that set such an ID in templateQuery to the current template types.
Sorting is applied before paging, first by template ID and then by a unique record ID for equal template IDs. As long as data, permissions, target user, filters and page size remain unchanged, the order stays stable while paging.
Update a document (/Update)
POST …/api/v3/{datasourceId}/Connect/Update updates an existing document created with primedocs and returns the updated file (conversion=Pdf is supported as with /Document). The functional details (handling of omitted values, language override, enabled remote sources) are described under Updating documents.
The document to update is supplied in one of three ways:
- Multipart (
multipart/form-data) with the partsdocument(the existing Office file) andconnect(the connect XML). If thedocumentpart is missing, a400with a corresponding hint is returned. - Inline as Base64 in the connect XML (body = plain connect XML):
<DocumentLocation Format="DocxBase64">…base64…</DocumentLocation>. - Server-side fetch via
<DocumentLocation Source="https://…"/>(only for remote sources enabled in the datasource settings).
| Query parameter | Description |
|---|---|
conversion (optional) | None (default) or Pdf. |
proposedFileName (optional) | Proposed file name. |
Forms and Data values that are not supplied are kept on every update, see Supplied and omitted values.
/Document and /Result reject update connects (with a DocumentLocation) and point to /Update with a 400. Conversely, /Update rejects plain generation connects.
Result
The result depends on the template type. In all cases, a file is created.
For Word, Excel and PowerPoint templates, it is a corresponding file.
Outlook
For all Outlook templates, HTML is returned by default, along with a list of linked images in json format:
{
"Body":"<html><head></head><body><p>Hello World</p>\r\n<p><b>My Firstname</b> My LastName</p>\r\n<img src=\"cid:profile-org-logo-1312016b.png\"></body></html>",
"AttachmentImages":[
{
"Name":"profile-org-logo-1312016b.png",
"Base64Data":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAA1JREFUGFdj+P//PwMACPwC/ohfBuAAAAAASUVORK5CYII="
}
]
}
Body: Contains the HTML content of the signature or email template. If image data from the profile is accessed in the template (e.g. via<img src="{{Profile.Org.Logo}}" />), the image is replaced via acid-link and stored inAttachmentImages.
Note: If external images are linked or images are stored directly via base64 in the template/signature, nocid-link is added. This only happens via primedocs images.AttachmentImages: Contains allcid-images.
<primedocsConnect>
<Template Id="e76712a7-d7ab-4112-9240-e688522e5f75" />
<Author>
<Profile Id="dfc92748-fbf2-4861-bfac-683fec6139fe" />
</Author>
<!-- This can be omitted, because this is the default: -->
<Outlook ContentType="Html" />
</primedocsConnect>
PlainText
PlainText signatures and email templates can also be defined via the Connect API. To do this, Connect must be configured with the Outlook-element:
<primedocsConnect>
<Template Id="e76712a7-d7ab-4112-9240-e688522e5f75" />
<Author>
<Profile Id="dfc92748-fbf2-4861-bfac-683fec6139fe" />
</Author>
<Outlook ContentType="PlainText" />
</primedocsConnect>
In this case, the following json is returned:
{
"PlainTextContent":"My Firstname My Lastname"
}
ConnectResultReport
The POST /Result endpoint returns a ConnectResultReport as JSON. It describes the outcome of the generation and the processing of the commands:
{
"Status": "OK",
"Message": null,
"Messages": [
{ "Type": "Info", "Message": "…" }
],
"CreatedOnUtc": "2026-01-01T12:00:00Z",
"Dialogs": [
{ "Title": "…", "Message": "…", "ButtonLabel": "…", "ButtonUri": "…" }
],
"HasDownload": false
}
| Field | Description |
|---|---|
Status | Outcome of the generation: OK, Error, Cancelled, Running, or Unknown. |
Message | Summary error message if Status is not OK (otherwise null). |
Messages | List of messages, each with Type and Message. The messages contain neither internal messages nor exception texts. Those are only in the server log. |
CreatedOnUtc | Completion time (UTC). |
Dialogs | Dialogs produced from ShowDialog commands (Title, Message, ButtonLabel, ButtonUri) for display in the client. |
HasDownload | true if a download (e.g. from a series output) is available. |
Authentication and call
To call the Connect APIs, a corresponding client must be registered in the primedocs.config, see primedocs.config.
After registration, an AccessToken can be requested from the IdS. The actual call can then be made against the Connect/Document endpoint of the WebApi using the AccessToken.
This PowerShell example shows how to obtain the AccessToken and call the endpoint:
# Configuration
$datasourceId = "b78c3707-d7c7-4fc7-b97f-87d70f63c1ac"
$tokenUrl = "https://{instanz}/ids/connect/token"
$baseApiUrl = "https://{instanz}/webapi/api"
$clientID = "CustomApiClient"
$clientSecret = "CustomClient_Secret_123"
$scope = "pd_ConnectWebApi"
$tokenRequestHeaders = @{
"Content-Type" = "application/x-www-form-urlencoded"
}
$tokenRequestBody = @{
client_id = $clientID
client_secret = $clientSecret
grant_type = "client_credentials"
scope = $scope
}
try {
$tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method POST -Headers $tokenRequestHeaders -Body $tokenRequestBody
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
if (-not $tokenResponse.access_token) {
Write-Error "Failed to obtain an access token!"
exit 1
}
Write-Host "Access Token: $($tokenResponse.access_token)"
$accessToken = $tokenResponse.access_token
$apiRequestHeaders = @{
"Authorization" = "Bearer $accessToken"
}
$putBodyRequestHeaders = @{
"Content-Type" = "application/json"
"Authorization" = "Bearer $accessToken"
}
$xmlBodyRequestHeaders = @{
"Content-Type" = "application/xml"
"Authorization" = "Bearer $accessToken"
}
function Show-Menu {
Write-Host "================ Main Menu ================"
Write-Host "1: Generate Document"
Write-Host "2: Validate Connect Form"
Write-Host "3: Create Connect Session"
Write-Host "4: Get Templates"
Write-Host "Q: Exit"
}
function GenerateDocument {
$connectFilePath = Read-Host "Enter connect file path"
$proposedFileName = Read-Host "Enter proposed file name (without extension, optional)"
$outputFilePath = Read-Host "Enter output file path (e.g., C:\\Temp\\Generated.docx)"
$pdfConversion = Read-Host "Convert result to pdf (y/n, default n)"
if (-not (Test-Path $connectFilePath)) {
Write-Error "Connect file not found: $connectFilePath"
return
}
$connectFileContent = Get-Content -Path $connectFilePath -Raw
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Connect/Document"
if (![string]::IsNullOrWhiteSpace($proposedFileName)) {
$apiUrl += "?proposedFileName=$proposedFileName"
}
if ($pdfConversion -eq "y" -or $pdfConversion -eq "Y") {
if ($apiUrl -like "*?*") {
$apiUrl += "&conversion=Pdf"
}
else {
$apiUrl += "?conversion=Pdf"
}
}
try {
Invoke-WebRequest -Uri $apiUrl -Method POST -Headers $xmlBodyRequestHeaders -Body $connectFileContent -OutFile $outputFilePath
Write-Host "File saved to: $outputFilePath"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}
function ValidateConnectForm {
$templateId = Read-Host "Enter Template ID"
$fieldKey = Read-Host "Enter field key"
$fieldValue = Read-Host "Enter field value"
$body = @{
templateId = $templateId
formValues = @{
$fieldKey = $fieldValue
}
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Connect/Validate"
try {
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))
$response = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $putBodyRequestHeaders -Body $utf8body
$response | ConvertTo-Json -Depth 6
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}
function CreateConnectSession {
$connectFilePath = Read-Host "Enter connect file path"
if (-not (Test-Path $connectFilePath)) {
Write-Error "Connect file not found: $connectFilePath"
return
}
$connectFileContent = Get-Content -Path $connectFilePath -Raw
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Connect/Session"
try {
$response = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $xmlBodyRequestHeaders -Body $connectFileContent
Write-Output "SessionId: $($response.sessionId)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}
function GetTemplates {
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
$userId = Read-Host "Enter userId (or empty)"
$userQuery = Read-Host "Enter userQuery (or empty)"
$templateQuery = Read-Host "Enter templateQuery (or empty)"
$uiLcid = Read-Host "Enter uiLcid (or empty)"
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Connect/Templates?pageSize=$($pageSize)&page=$($page)"
if (![string]::IsNullOrWhiteSpace($userId)) { $apiUrl += "&userId=$userId" }
if (![string]::IsNullOrWhiteSpace($userQuery)) { $apiUrl += "&userQuery=$userQuery" }
if (![string]::IsNullOrWhiteSpace($templateQuery)) { $apiUrl += "&templateQuery=$templateQuery" }
if (![string]::IsNullOrWhiteSpace($uiLcid)) { $apiUrl += "&uiLcid=$uiLcid" }
try {
$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders
foreach ($template in $response.data) {
Write-Output "$($template.id): $($template.localizedName)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}
do {
Show-Menu
$selection = Read-Host "Please select an option"
switch ($selection) {
'1' { GenerateDocument }
'2' { ValidateConnectForm }
'3' { CreateConnectSession }
'4' { GetTemplates }
'Q' { break; }
Default {
Write-Host "Invalid option selected"
}
}
} while ($selection -ne 'Q')
Error handling
The HTTP status codes, the problem document and the error codes are described uniformly for all API areas under API → Error handling. For the Connect API:
400 Bad Requestfor errors in the Connect that the caller can fix: malformed or empty Connect XML, a missingAuthorelement, invalid language codes, an invalidDocumentLocationformat or commands that are not supported on the server (Connect.Invalid,Connect.Empty,Connect.NotSupported).422 Unprocessable EntitywithcodeConnect.ExecutionFailed(not for/Result) if the Connect is valid but the generation fails on an expected error, for example invalid form values, faulty content inData, an unsupported document language, missing MIP access or a Connect policy.detailanderrorsgive the reasons, for form errors including the affected field ID.500 Internal Server Erroronly for unexpected technical errors, with a generic message andcorrelationId.
For an execution error, the POST /Result endpoint does not respond with 422 but with 200 OK and a ConnectResultReport with Status: "Error" and a Message. 400 and 500 apply as above.
Swagger / Open API
The full, always up-to-date OpenAPI description can be obtained directly from a running instance, e.g. from the PrimeSoft reference instance:
https://primesoft.primedocs.io/webapi/swagger/index.html
You can also visualise the description using the Swagger Editor. Below is the excerpt for the Connect/Document endpoint as an example:
{
"openapi": "3.0.1",
"info": {
"title": "primedocs WebApi",
"version": "v3"
},
"paths": {
"/api/v3/{datasourceId}/Connect/Document": {
"post": {
"tags": ["Connect"],
"parameters": [
{
"name": "proposedFileName",
"in": "query",
"schema": { "type": "string" }
},
{
"name": "conversion",
"in": "query",
"schema": { "type": "string", "enum": ["None", "Pdf"] }
},
{
"name": "datasourceId",
"in": "path",
"required": true,
"schema": { "type": "string", "format": "uuid" }
}
],
"responses": {
"200": { "description": "Success" }
}
}
}
}
}