External sources

REST interface

Take over documents from your own system through an HTTP/JSON interface – with a request chain, variables and a field mapping.

With the REST interface system type, DDM fetches documents from a system that offers them through an HTTP interface – a DMS, a PIM, a shop, your own application. Unlike with SharePoint or FTP, DDM does not know how this interface is built. You describe it in a request chain: which addresses DDM calls, where in the response the list of documents is and what each value means.

That sounds more technical than the other sources – and it is. Expect to need somebody who knows the interface and has its documentation to hand.

Available from the Enterprise plan – see Plans.

What the interface must be able to do

DDM needs two things from it:

  1. A list of the documents as JSON (or XML) – with at least a name and an address where the file is.
  2. The file itself at this address, retrievable with a simple GET.

Authentication is with one fixed header, e.g. an API token. A sign-in that first fetches a token can be modelled as a step of its own – see Example 3.

1. Add the source

Under Settings › External sources, add a source with New source, give it a name and choose REST interface as the System type.

FieldWhat to enter
Base URLThe interface's common address, e.g. https://dms.company.com/api/v1. The steps' paths are appended to it
Authentication (header)One header in the format Name: Value, e.g. Authorization: Bearer eyJhbGc… or X-API-Key: 7f3a…. For Basic Auth: Authorization: Basic and user:password in Base64. Stored encrypted, never shown again

DDM sends this header only to the base URL – more precisely: to addresses with the same protocol, host and port. If a step calls another address or a file is on another server, the header is not sent there.

If you change the Base URL, DDM deletes the stored Authentication – a token belongs to its server. Enter it again afterwards.

Click Test connection. DDM calls the base URL with GET and the header.

MessageWhat to do
The interface answers (HTTP …).The address is reachable. Even a 404 or 405 counts as „answers" here – many interfaces have nothing at the base URL itself. Whether the actual calls work is only shown by Test chain.
The interface rejected the credentials — check the authentication header.Response 401 or 403 – the header is wrong or the token has expired.
The address redirects to … — please enter the target URL directly.DDM does not follow redirects. Enter the address named as the base URL – often only https:// or a / at the end is missing.
This address may not be fetched (…).The address is blocked – e.g. not http/https, or with a hosted DDM an address on a private network.
The address does not answer — check the URL, the port and the firewall.The server cannot be reached.
The stored authentication can no longer be decrypted — please enter it again.Enter the header again.

2. Understanding the request chain

Under Request chain & field mapping, add one or more steps with + Step. Each step is one call to the interface. The steps run one after another:

  • A step can iterate over a list in its response – for each entry, the next step runs once.
  • A step can hand values on to the following ones as variables, e.g. a folder's ID.
  • A field mapping says which value of the response is which detail of a document: name, file URL, category …

At the end, every entry of the last step that returned entries becomes a document – provided it has a name and a file URL.

A step

FieldMeaning
NameFor you, e.g. „List documents"
CallThe method – GET, POST, PUT or DELETE – and the Path: relative to the base URL (documents) or a full address (https://…) – see Path and base URL
HeadersAdditional headers for this step, one per line, e.g. Accept: application/json or X-Tenant: 42. They are always sent, to other servers too, and take precedence over the source's
BodyOnly with POST and PUT: the content of the request, e.g. JSON. DDM sets the matching Content-Type itself – application/json for JSON, text/xml for XML –, unless the step names its own under Headers
Iterate over listWhere in the response the list is, e.g. items or data.documents. Empty = the whole response is one entry
Step activeThe chain skips inactive steps

With the arrows Move up / Move down you change the order.

Path and base URL

A step's path always goes below the base URL – whether it starts with / or not:

Base URLPathDDM calls
https://dms.company.com/api/v1documents or /documentshttps://dms.company.com/api/v1/documents
https://dms.company.com/api/v1?page=2https://dms.company.com/api/v1?page=2
https://dms.company.com/api/v1(empty) or /https://dms.company.com/api/v1
https://dms.company.com/api/v1https://cdn.company.com/xhttps://cdn.company.com/x

A document's File URL is different: it comes from your interface's response and is read like a link. If the interface returns /files/4711, DDM downloads https://dms.company.com/files/4711 – from the server root, not below /api/v1. That is what interfaces mean by such addresses.

Paths in the response

You give the place where a value is as a dotted path – not JSONPath, not XPath:

{
  "data": {
    "items": [
      { "id": 4711, "title": "Pricelist 2026", "file": { "url": "/files/4711" }, "tags": ["sales"] }
    ]
  }
}
Pathgives
data.itemsthe list – this goes into Iterate over list
titlePricelist 2026 – relative to the single entry of the list
file.url/files/4711
tags.0sales – numbers access lists, starting at 0
(empty)the whole entry

Paths in variables and field mappings always apply to one entry of the iterated list, not to the whole response.

Variables

Under Variables for later steps, set a Variable name and a JSON path with + Variable. In every later step you insert the value with {{name}} – in the Path, the Headers or the Body:

  • Path: folders/{{folderId}}/files
  • Header: Authorization: Bearer {{token}}
  • Body: { "folder": "{{folderId}}" }

DDM inserts the values appropriately: URL-encoded in the path, in the body as JSON or XML text depending on the content. A variable name may only contain unaccented letters, digits, _, . and -. Under Incoming variables, each step shows which variables the earlier ones provide; one it uses is highlighted.

A path that consists only of a variable containing a full address – {{nextPage}} – is called unchanged.

Field mapping

Under Field mapping (JSON → attribute), map a path to a detail of the document with + Mapping:

AttributeMeaning
Document nameName of the document in DDM. The File filter goes by this name – with extension, e.g. Pricelist.pdfrequired
File URLWhere the file is – relative to the base URL or complete. DDM downloads it with GETrequired
External idAn ID that never changes in your system. DDM uses it to recognise the document at the next sync, even if it has been renamedstrongly recommended
Category pathThe category, separated by /, e.g. Sales/Prices. Used according to the Category mapping in the import scope
File typeThe MIME type, e.g. application/pdf. Without it, whatever the server reports on download applies
External groupA group from your system that is to get read access – see Group mapping
Size (bytes), Modified atCan be mapped but have no effect – DDM takes the file's actual size and detects changes by content

Mappings in earlier steps apply to all entries that arise below them. So step 1 can, for example, provide the Category path from the folder name, and step 2 the name and file URL of the files in it.

Without an External id, DDM recognises a document only by its name in its category. If your system renames it, a second one is created in DDM.

Transformations

Every variable and every mapping can reshape the value before it is used:

TransformationExample
None–
Lowercase / UppercaseSales → sales / SALES
Trim whitespacePricelist → Pricelist
Add prefix4711 with prefix dms- → dms-4711
Add suffixPricelist with suffix .pdf → Pricelist.pdf – useful when the name has no extension
ReplaceSearch for \ Replace with / → Sales\Prices becomes Sales/Prices
Cut at separatorWith separator ?: list.pdf?v=3 becomes list.pdf

Beside each row, a preview shows what becomes of the first entry of the example response.

3. Test the chain

Click Test chain (or Test on a single step). DDM calls the steps without importing anything, and shows

  • a status per step: ok, failed, skipped, unreachable, rejected, redirected or address blocked,
  • under Example response, the step's response (the first 20,000 characters) – the basis for the previews,
  • how many records resulted,
  • in the Import scope under Structure preview, which path would go into which category,
  • under Group mapping, the Groups found.

If a step fails (HTTP status 400 or above, or no response), the chain stops and the following steps are set to skipped. Beneath the failed step you see what came back – the status and the start of the response, e.g. the interface's error message. The Example response keeps the last successful response, so the previews are not lost. You can also paste the Example response by hand – e.g. from the interface's documentation – to prepare mappings before the connection is in place.

Once the chain works, sync once with Sync now in the Import scope and switch on Source active – see Overview.

Examples

Example 1: One list, one call

The interface returns under GET /documents:

{ "items": [ { "id": "4711", "title": "Pricelist.pdf", "url": "/files/4711", "folder": "Sales/Prices" } ] }

Step 1 – „Documents": GET documents, Iterate over list items.

JSON pathAttribute
titleDocument name
urlFile URL
idExternal id
folderCategory path

Example 2: First the folders, then their files

GET /folders returns the folders, GET /folders/{id}/files the files of a folder.

Step 1 – „Folders": GET folders, Iterate over list items.

  • Variable id = id
  • Mapping name → Category path

Step 2 – „Files": GET folders/{{id}}/files, Iterate over list files.

  • Mappings title → Document name, url → File URL, fileId → External id

Step 2 runs once per folder from step 1; each file gets the category path of its folder.

Example 3: Sign in first, then fetch

After POST /auth/token, the interface returns a short-lived token:

{ "access_token": "eyJhbGc…", "expires_in": 3600 }

Step 1 – „Sign in": POST auth/token, Body:

{ "client_id": "ddm", "client_secret": "…" }
  • Variable token = access_token
  • Iterate over list: empty

Step 2 – „Documents": GET documents, Headers Authorization: Bearer {{token}}, Iterate over list items, mappings as in example 1.

What is in a step's Body, DDM stores unencrypted, and every administrator can see it – unlike the Authentication (header) field. Only use this approach if the interface offers no fixed token, and give DDM its own credentials with read rights only.

The downloaded files only get the header from Authentication (header) – not the token from step 1. If your server requires the token for the files too, the file URL itself must contain the access (such as a signed address), or the server must deliver files with the fixed header.

Group mapping

If your interface returns a group for each document – a department, a role, a customer group –, DDM can turn it into read access:

  1. In the chain, map the group's path to the External group attribute.
  2. Click Test chain. Under Group mapping, the Groups found appear.
  3. Click a group found (or + Mapping and type its name) and choose the DDM group that gets it.

On sync, every document gets read access for the DDM group mapped to its external group – in addition to the permissions of its category. Upper and lower case do not matter.

  • Without a mapping, with No group or with Mapping active switched off, the import grants no rights for this group.
  • Each document can have one external group.
  • The import only grants rights, it never withdraws them. If a document's group changes in your system, the old DDM group keeps its read access – withdraw it on the document if needed.

Limits

LimitValue
Calls per sync, all steps together40
Entries per step200
Size of a response2 MB
Time per call30 seconds (20 when testing)
Time per file download60 seconds
Largest file25 MB

DDM does not follow redirects (HTTP 3xx) – enter the target address directly.

There is no built-in paging (pagination): each step runs once per entry of the previous one, not „until nothing more comes". If your interface returns pages, request pages as large as possible (e.g. ?limit=200), or model a fixed number of pages as steps of their own – for instance with the variable {{nextPage}} from the first page's response as the path of the second step. If the maximum number of calls is reached, the test reports Stopped at the maximum number of calls …; split the source up then.