Reference: documents
Base address: https://<your CMS address>/api/ext/v1. Every request needs Authorization: Bearer <key>. Scope says what the key needs.
The document object
pdf.id, versionNo, checksum (SHA-256, hex), sizeBytes, mimeType, createdAt.updatedAt is the last change – see Change feed.PUT /documents/ref/{ref} – push
Scope write. Creates the document with this reference in the key's push source, or updates it. See Pushing documents.
Body: multipart/form-data with
name, categoryPath, categoryIds, categoryRefs, mimeType, tags, titles, groupName – all optional. With categoryIds and/or categoryRefs the document is filed exactly there, with categoryPath in the path's category as well.or application/json with the same fields as metadata, plus
Answer: 201 (created) or 200, with { "outcome": "created" | "versioned" | "unchanged" | "skipped", "document": Document | null }.
Errors: 400 invalid metadata · 403 read-only key, push source missing or switched off, missing permissions · 409 an approval is running · 413 file too large or storage full · 415 wrong Content-Type · 422 fileUrl could not be fetched.
Request
curl -X PUT "https://ddm.example.com/api/ext/v1/documents/ref/PIM-4711" \
-H "Authorization: Bearer $DDM_API_KEY" \
-F "file=@Price-list-2026.pdf;type=application/pdf" \
-F 'metadata={"categoryPath": "Products/Price lists", "tags": ["Prices", "2026"], "titles": {"DE": "Preisliste 2026"}};type=application/json'
Response · 201 Created
{
"outcome": "created",
"document": {
"id": "dc8594e0-0ead-4049-aaee-2ef899bcf76f",
"externalRef": "PIM-4711",
"sourceId": "5d02b7aa-5175-42e9-9277-aa19063833f2",
"name": "Price-list-2026.pdf",
"fileType": "pdf",
"mimeType": "application/pdf",
"sizeBytes": 589,
"status": "draft",
"shareable": true,
"highlighted": false,
"titles": {
"DE": "Preisliste 2026"
},
"tags": [
"2026",
"Prices"
],
"categoryIds": [
"078a554f-19a2-4285-b854-8546de01f815"
],
"currentVersion": {
"id": "b5a8ce67-c8f1-439a-aadb-86e1b73223e2",
"versionNo": 1,
"checksum": "5db6ba22797a193286fdebf4919730b4571146bde75bb4ad3dc856a38f2f71c1",
"sizeBytes": 589,
"mimeType": "application/pdf",
"createdAt": "2026-10-27T20:01:46.510Z"
},
"createdAt": "2026-10-27T20:01:46.510Z",
"updatedAt": "2026-10-27T20:01:46.838Z"
}
}
Sending the same file again, then a changed one:
200,"outcome": "unchanged"– the same version200,"outcome": "versioned"–currentVersion.versionNois now 2
PUT /documents/{id} – new bytes by id
Scope write. The same content as a push – multipart with file and metadata, or JSON with fileUrl – for a document you address by DDM's id:
- If it belongs to the key's push source, this is the same as
PUT /documents/ref/{ref}with its reference – by the source's rules. - Any other document, e.g. one uploaded in the CMS, gets a new version as an upload would.
tags,titles,categoryIdsandcategoryRefsapply as for a push.
Answer: 200 with outcome and the document.
GET /documents – list and change feed
Scope read. Documents the key can see, oldest change first.
nextCursor of the previous page.categoryId.categoryId or categoryRef: include the categories below it.Answer: { "data": Document[], "nextCursor": string | null }.
Request
curl "https://ddm.example.com/api/ext/v1/documents?limit=2&own=true" \
-H "Authorization: Bearer $DDM_API_KEY"
Response · 200 OK
{
"data": [
{
"id": "dc8594e0-0ead-4049-aaee-2ef899bcf76f",
"externalRef": "PIM-4711",
"sourceId": "5d02b7aa-5175-42e9-9277-aa19063833f2",
"name": "Price-list-2026.pdf",
"fileType": "pdf",
"mimeType": "application/pdf",
"sizeBytes": 605,
"status": "draft",
"shareable": true,
"highlighted": false,
"titles": {
"DE": "Preisliste 2026"
},
"tags": [
"2026",
"Prices"
],
"categoryIds": [
"078a554f-19a2-4285-b854-8546de01f815"
],
"currentVersion": {
"id": "1730e7bb-2f98-4761-aa9b-964c521351b3",
"versionNo": 2,
"checksum": "0bcb7c3b4886f699a985563d7bc9476bf75b4af35a57ff959f46c37e386cf54f",
"sizeBytes": 605,
"mimeType": "application/pdf",
"createdAt": "2026-10-27T20:01:46.904Z"
},
"createdAt": "2026-10-27T20:01:46.510Z",
"updatedAt": "2026-10-27T20:01:47.169Z"
}
],
"nextCursor": null
}
GET /documents/{id} · GET /documents/ref/{ref}
Scope read. One document. 404 if it does not exist or the key cannot see it. By reference only within the key's push source.
Request
curl https://ddm.example.com/api/ext/v1/documents/dc8594e0-0ead-4049-aaee-2ef899bcf76f \
-H "Authorization: Bearer $DDM_API_KEY"
curl https://ddm.example.com/api/ext/v1/documents/ref/PIM-4711 \
-H "Authorization: Bearer $DDM_API_KEY"
Response · 200 OK
{
"id": "dc8594e0-0ead-4049-aaee-2ef899bcf76f",
"externalRef": "PIM-4711",
"sourceId": "5d02b7aa-5175-42e9-9277-aa19063833f2",
"name": "Price-list-2026.pdf",
"fileType": "pdf",
"mimeType": "application/pdf",
"sizeBytes": 605,
"status": "draft",
"shareable": true,
"highlighted": false,
"titles": {
"DE": "Preisliste 2026"
},
"tags": [
"2026",
"Prices"
],
"categoryIds": [
"078a554f-19a2-4285-b854-8546de01f815"
],
"currentVersion": {
"id": "1730e7bb-2f98-4761-aa9b-964c521351b3",
"versionNo": 2,
"checksum": "0bcb7c3b4886f699a985563d7bc9476bf75b4af35a57ff959f46c37e386cf54f",
"sizeBytes": 605,
"mimeType": "application/pdf",
"createdAt": "2026-10-27T20:01:46.904Z"
},
"createdAt": "2026-10-27T20:01:46.510Z",
"updatedAt": "2026-10-27T20:01:47.169Z"
}
PATCH /documents/{id} · PATCH /documents/ref/{ref}
Scope write. Changes only what is sent:
null clears an end.categoryIds both count: 1–20 categories in all.Answer: the document. Errors: 400, 403, 404, 409 (approval running).
Request
curl -X PATCH https://ddm.example.com/api/ext/v1/documents/dc8594e0-0ead-4049-aaee-2ef899bcf76f \
-H "Authorization: Bearer $DDM_API_KEY" -H "Content-Type: application/json" \
-d '{"shareable":false,"tags":["Prices","2026","Export"]}'
curl -X PATCH https://ddm.example.com/api/ext/v1/documents/ref/PIM-4711 \
-H "Authorization: Bearer $DDM_API_KEY" -H "Content-Type: application/json" \
-d '{"shareable":false,"tags":["Prices","2026","Export"]}'
Response · 200 OK
{
"id": "dc8594e0-0ead-4049-aaee-2ef899bcf76f",
"externalRef": "PIM-4711",
"sourceId": "5d02b7aa-5175-42e9-9277-aa19063833f2",
"name": "Price-list-2026.pdf",
"fileType": "pdf",
"mimeType": "application/pdf",
"sizeBytes": 605,
"status": "draft",
"shareable": false,
"highlighted": false,
"titles": {
"DE": "Preisliste 2026"
},
"tags": [
"2026",
"Export",
"Prices"
],
"categoryIds": [
"078a554f-19a2-4285-b854-8546de01f815"
],
"currentVersion": {
"id": "1730e7bb-2f98-4761-aa9b-964c521351b3",
"versionNo": 2,
"checksum": "0bcb7c3b4886f699a985563d7bc9476bf75b4af35a57ff959f46c37e386cf54f",
"sizeBytes": 605,
"mimeType": "application/pdf",
"createdAt": "2026-10-27T20:01:46.904Z"
},
"createdAt": "2026-10-27T20:01:46.510Z",
"updatedAt": "2026-10-27T20:01:47.260Z"
}
DELETE /documents/{id} · DELETE /documents/ref/{ref}
Scope write. Deletes the document. Answer: 204. Errors: 403, 404, 409 (retention hold, approval running).
Request
curl -X DELETE https://ddm.example.com/api/ext/v1/documents/dc8594e0-0ead-4049-aaee-2ef899bcf76f \
-H "Authorization: Bearer $DDM_API_KEY"
curl -X DELETE https://ddm.example.com/api/ext/v1/documents/ref/PIM-4711 \
-H "Authorization: Bearer $DDM_API_KEY"
Response · 204 No Content – No body.
GET /documents/{id}/content · GET /documents/ref/{ref}/content
Scope read. The file.
Headers: Range, If-None-Match. Answer: 200, 206 or 304, with Content-Type, Content-Length, ETag and Content-Disposition. With a released content key, only documents that may leave the app (shareable) can be downloaded (otherwise 403).
Request
curl -o Price-list-2026.pdf -D - \
https://ddm.example.com/api/ext/v1/documents/dc8594e0-0ead-4049-aaee-2ef899bcf76f/content \
-H "Authorization: Bearer $DDM_API_KEY"
Response · 200 OK – Headers of the answer – the body is the file itself:
HTTP/1.1 200 OK
accept-ranges: bytes
content-disposition: attachment; filename="Price-list-2026.pdf"; filename*=UTF-8''Price-list-2026.pdf
content-length: 605
content-type: application/pdf
etag: "1730e7bb-2f98-4761-aa9b-964c521351b3"
With the last ETag as If-None-Match, an unchanged file answers without a body:
HTTP/1.1 304 Not Modified
cache-control: private, max-age=300, must-revalidate
etag: "1730e7bb-2f98-4761-aa9b-964c521351b3"
With Range: bytes=0-99, only part of it:
HTTP/1.1 206 Partial Content
accept-ranges: bytes
content-disposition: attachment; filename="Price-list-2026.pdf"; filename*=UTF-8''Price-list-2026.pdf
content-length: 100
content-range: bytes 0-99/605
content-type: application/pdf
etag: "1730e7bb-2f98-4761-aa9b-964c521351b3"
GET /documents/{id}/text · GET /documents/ref/{ref}/text
Scope read. The text DDM read out of the current version, for a search index: { "versionId", "versionNo", "language", "content" }. Follows the readers' rules, including for a key that sees everything.
Request
curl https://ddm.example.com/api/ext/v1/documents/dc8594e0-0ead-4049-aaee-2ef899bcf76f/text \
-H "Authorization: Bearer $DDM_API_KEY"
Response · 200 OK
{
"versionId": "1730e7bb-2f98-4761-aa9b-964c521351b3",
"versionNo": 2,
"language": null,
"content": "Price list 2026, second edition"
}
GET /documents/{id}/thumbnail · GET /documents/ref/{ref}/thumbnail
Scope read. The preview image of the first page. versionId as for content.
Request
curl -o preview.webp https://ddm.example.com/api/ext/v1/documents/dc8594e0-0ead-4049-aaee-2ef899bcf76f/thumbnail \
-H "Authorization: Bearer $DDM_API_KEY"
Response · 200 OK – Headers of the answer – the body is the file itself:
HTTP/1.1 200 OK
cache-control: private, max-age=300, must-revalidate
content-length: 5052
content-type: image/webp
etag: "1730e7bb-2f98-4761-aa9b-964c521351b3"