REST API
The REST API provides the ability to browse data, statuses, and parameters maintained by MDM via REST interfaces. The API supports REST Maturity Level 2.
By default, the REST API uses the default server port (8051) set in MDM Server Application Properties.
The path to REST API is /api/rest and it cannot be configured.
Every call requires authentication and the MDM_rest_api_access or MDM_admin role, see Authentication and authorization.
The following sections describe the uses of the REST API. For walkthroughs of common tasks that combine several endpoints, see REST API Scenarios.
Authentication and authorization
REST API requests are authenticated with a bearer token. Basic HTTP authentication is still accepted but deprecated. For details, see API Requests Authentication.
To use the REST API and make changes to master data, you need:
-
One of required user roles, which grants you access to the REST API.
-
Permissions for the entities and operations you want to work with. See Security and Audit > Permissions required by REST API endpoints.
Required user role
To call the REST API, a user or service account needs the MDM_rest_api_access or MDM_admin role.
Assign MDM_rest_api_access to every integration service account, ETL or scripting user, and anyone who uses Try it out in Swagger UI.
Without the role, every request returns a 403 Forbidden HTTP status code with an empty body.
These requests are not audited.
The required roles are defined by the api-rest access control list in the MDM Server application properties, where you can also allow other roles.
See MDM Server Application Properties > API endpoint required role configuration.
Permissions
Once you have the necessary user role, what you can actually read and change is determined by the permissions your roles have in nme-security.xml:
-
Read and write permissions, such as
ReadEntitiesandWriteAll: Allow you to read or write records.Permissions apply per entity, not per operation. If you can write
partyrecords, you can also create, update, delete, merge, and rematch them.A permission can be further limited to certain columns, source systems, or records; those same restrictions apply in the REST API.
-
System operations permissions, such as
OpsViewandOpsWrite: Allow you to perform purge operations and system tasks, work with event handlers or persistence. -
Batch load and export permissions, such as
BatchOpsAllorBatchOpsByName: Allow you to call batch endpoints. -
AllPermissions: Grants all permissions. Assign with caution.
For details, see Security and Audit > Authorization.
Denied requests
If you have the required role but not the permission for an operation, the response is 403 Forbidden with the standard JSON error body (see Response status codes):
{
"title": "Forbidden",
"status": 403,
"detail": "Unauthorized attempt to READ_TYPE by james.jones",
"instance": "/api/rest/instance/party/1/override"
}
The detail field tells you which permission is missing:
detail |
Missing permission |
|---|---|
|
Read permission for the entity. |
|
Write permission for one of the entities the operation changes. |
|
You have write permission for the entity, but its record conditions or source systems exclude this particular record. Nothing from the request is saved. |
|
|
A denied request returns 403 Forbidden even if the request body is invalid or the record does not exist.
An unknown entity or master view returns 404 Not Found regardless of your permissions.
Every request denied for a missing permission is recorded as an UNAUTHORIZED audit event; see Security and Audit > Auditing.
OpenAPI Swagger
The Swagger UI allows you to see a list of available REST API endpoints and operations in a browser-based HTML interface. The Swagger UI includes descriptions for all endpoints, parameters, and schemas.
http://localhost:8051/swagger-ui.html
|
The OpenAPI specification is available at Swagger uses the |
Listing REST endpoints
A response contains a directory of exposed services and interfaces and additional information, including the RW mode.
http://localhost:8051/api/rest/
{
"name" : "REST API",
"version" : "1.0",
"rwmode" : "RW",
"uris" : {
"tasks" : "http://localhost:8051/api/rest/tasks",
"eventHandlers" : "http://localhost:8051/api/rest/event-handlers",
"instance" : "http://localhost:8051/api/rest/instance",
"master" : "http://localhost:8051/api/rest/master",
"persistence" : "http://localhost:8051/api/rest/persistence",
"purge" : "http://localhost:8051/api/rest/purge",
"parameters" : "http://localhost:8051/api/rest/parameters",
"operationPlan" : "http://localhost:8051/api/rest/operation-plan",
"sourceSystems" : "http://localhost:8051/api/rest/source-systems",
"statistics" : {
"instance" : "http://localhost:8051/api/rest/statistics/instance",
"master" : "http://localhost:8051/api/rest/statistics/master"
},
"interfaces" : {
"services" : "http://localhost:8051/api/rest/interfaces/services",
"exports" : "http://localhost:8051/api/rest/interfaces/batch/exports",
"loads" : "http://localhost:8051/api/rest/interfaces/batch/loads",
"consumers" : "http://localhost:8051/api/rest/interfaces/streaming/consumers"
}
}
}
The rwmode field indicates the read/write mode of the engine.
Possible values are RW (read-write) and RO (read-only).
Response status codes
The MDM REST API uses standard HTTP status codes for error and status reporting.
These codes are categorized as follows:
| Category | Description |
|---|---|
2xx |
Success |
3xx |
Redirection: this usually indicates a configuration error related to authentication, for example, the OAuth flow used. |
4xx |
Indicates a client error, an invalid request. |
5xx |
Indicates a server error. |
Common error codes
The following is a more detailed list of error codes that the REST API can return.
| Error code | Description |
|---|---|
400 Bad Request |
The request is invalid. For example, there are required parameters missing, an error in JSON formatting, an unknown column name, or some other error, as explained in the response. If the request body doesn’t match the expected schema, |
401 Unauthorized |
The request has no valid authentication token. |
403 Forbidden |
The caller does not have the |
404 Not Found |
A named resource in the URL does not exist, usually an entity, a master view, or a record. |
409 Conflict |
The request conflicts with the current state, for example, the resource is not in a valid state for the requested operation. |
500 |
A server error, for example, a configuration problem or failure during a write operation. |
Error responses use the RFC 7807 problem details format with the application/problem+json content type:
{
"title": "Not Found",
"status": 404,
"detail": "Cannot find seed record with id 999999999",
"instance": "/api/rest/master/masters/party/999999999/traverse"
}
The fields contain the following:
-
title: The standard HTTP reason phrase. -
status: Repeats the HTTP status code. -
detail: A human-readable description of what went wrong. -
instance: The path of the request that caused the error.
The optional type field is included only when it is explicitly set.
Server errors (5xx) also include an errorId field that correlates the response with the corresponding entry in the server error log.
Provide this identifier when contacting support.
In versions earlier than 17.2.0, error responses used a different structure with message and exception fields and the application/json content type.
For details, see MDM 17.2.0 Upgrade Notes.
Read records
A GET request is used to access instance and master layer information, entity information, records, or a single record.
If {origin} contains a #, it must be escaped as %23 in the URI.
|
Instance layer
| Endpoint | Description |
|---|---|
/instance |
Returns a list of entities on the instance layer. |
/instance/{entity} |
Returns all the records of the selected instance entity. |
/instance/{entity}/metadata |
Returns the metadata of the selected instance entity: columns, relationships, and ways to access a particular record. |
/instance/{entity}/{id} |
Returns an instance record by its |
/instance/{entity}/{origin}/{sourceId} |
Returns an instance record by its |
Master views
| Endpoint | Description |
|---|---|
/master |
Returns a list of master views. |
/master/{view} |
Returns a list of entities on the selected master view. |
/master/{view}/{entity} |
Returns all the records of the selected master view. |
/master/{view}/{entity}/metadata |
Returns the metadata of the selected master entity: columns and ways to access a particular record. |
/master/{view}/{entity}/{id} |
Returns a master record by its |
/master/{view}/{entity}/{origin}/{sourceId} |
Returns a master record by the |
Parameters
Results and their presentation can be customized with the following parameters:
| Parameter | Description |
|---|---|
columns |
Comma-separated list of columns that should be returned (by default all columns are returned). |
offset |
Used for paging. Offsets the first returned record, starts at 0. |
page |
Used for paging.
Alternative to offset - returns nth page, that is, offset=page*count, starts at 0.
Cannot be combined with |
count |
When used alone or with |
sort |
Name of the column to sort records by, optionally suffixed with |
<column_name>=<value> |
Filters by the exact value of the column with wildcard support. Multiple values of one column are supported: separate them by a comma, which acts as OR. System columns are also supported. |
preload=<relationship1>,<relationship2> |
Lists related records according to the provided relationships. On the master record and list endpoints, a relationship name can carry an inline filter in parentheses, for example,
The instance endpoints accept relationship names only. If you add a filter, it is rejected as an unknown relationship name. |
GET /instance/{entity}?offset=2&count=5
GET /instance/{entity}?columns=src_first_name,src_sin&src_first_name=Joh*&sort=std_birth_date:DESC
GET /master/{view}/{entity}?offset=2&count=5
GET /master/{view}/{entity}?columns=cmo_first_name,cmo_sin&cmo_first_name=Joh*&sort=cmo_birthdate:DESC
GET /master/{view}/{entity}?eng_active=true
GET /instance/{entity}?preload=contacts,addresses
// advanced preload examples
GET /master/masters/party?preload=addresses(cmo_street=*Logan*,cmo_city=*nto,cmo_state=Ont*,cmo_zip=*)
GET /master/masters/party?preload=addresses(cmo_city=is empty,eng_creation_tid=74005)
GET /master/masters/party/1020?preload=addresses.instances,contacts
GET /master/masters/party/1020?preload=addresses(cmo_type=Residential,cmo_state=US)
Sample GET requests and responses
GET /instance/party/1007
{
"type": "party",
"metadata":
{
"id": 1007,
"origin": "crm#customer#party",
"sourceSystem": "crm",
"active": true,
"sourceTimestamp": "2015-07-23T14:14:04Z",
"creationDate": "2017-09-08T15:39:59Z",
"lastUpdateDate": "2017-09-08T15:40:03Z",
"lastSourceUpdateDate": "2017-09-08T15:40:03Z",
"activationDate": "2017-09-08T15:39:59Z",
"creationTid": 1002,
"lastUpdateTid": 2814,
"lastSourceUpdateTid": 2814,
"activationTid": 1002
},
"attributes":
{
"source_id": "1001",
"master_id": 1238,
"propose_id": 1273,
"src_first_name": "DR. JOHN",
...
},
...
}
GET /master/masters/party/1235
{
"type": "party",
"metadata": {
"id": 1235,
"active": true,
"creationDate": "2017-09-08T15:39:59Z",
"lastUpdateDate": "2017-09-08T15:39:59Z",
"activationDate": "2017-09-08T15:39:59Z",
"creationTid": 1002,
"lastUpdateTid": 1002,
"activationTid": 1002
},
"attributes": {
"cmo_type": "P",
"cmo_first_name": "John",
...
}
}
Identify
The identify service checks whether a record is similar to any record stored in the hub. Input is in the form of the instance entity, while similarity is defined by the matching rules of this entity. Output is either matching information and master record or nothing.
The service accepts POST requests at the /master/{view}/{entity}/identify endpoint with the following structure:
POST /master/masters/party/identify
{
"sourceSystem" : "life",
"record" : {
"attributes" : {
"src_first_name" : "Anto",
"src_last_name" : "Lese",
"src_sin" : "387958572"
},
"relationships" : [{
"contacts" : [{
"attributes": {
"src_type" : "PHONE",
"src_value" : "416-206-1234"
}
},
{
"attributes": {
"src_type" : "EMAIL",
"src_value" : "alese@aol.com"
}
}]
}]
}
}
As an input, the service gets:
-
One record of the instance entity - attributes of origin
SOURCE. -
Records of related entities (optional) - attributes of origin
SOURCE.
The service cleanses input data and tries to match the record to records in the hub using matching rules. If the input record is matched to a master group, a master record is returned. For example, the response if the record is matched is:
{
"matchMetadata" : {
"matchRelatedId" : 1007,
"matchQuality" : 0.0,
"matchRuleName" : "name+sin"
},
"record" : {
"type" : "party",
"metadata" : {
"id" : 1030
// more metadata
},
"attributes" : {
"cmo_name" : "John",
// more attributes
}
}
}
If matching has proposals enabled, proposals are returned as well. It is possible to have only proposals in response (record matches only using proposal rules).
{
"matchMetadata" : { /* ... */ },
"record" : { /* ... */ },
"proposals" : [ {
"matchMetadata" : {
"matchRelatedId" : 1007,
"matchQuality" : 0.0,
"matchRuleName" : "name+sin"
},
"record" : {
"type" : "party",
"metadata" : {
"id" : 1030
// more metadata
},
"attributes" : {
"cmo_name" : "John",
// more attributes
}
}
},
// more proposals
]
}
If there are too many proposals (more than the runtime parameter nme.services.range.maxCount, default 100), proposals are returned in a short format:
{
"matchMetadata" : { /* filled */ },
"record" : { /* */ },
"proposals" : [ {
"masterId" : 1012,
"matchRelatedId" : 1007,
"matchQuality" : 0.0,
"matchRuleName" : "name+sin"
}
// more proposals
]
}
Identify in mixed style
When mixed style is used, master data combines consolidated records with authored records created directly in the master layer. To see if a master record being created would be a duplicate, evaluate the master layer matching rules over a record draft using the following request:
POST /master/{view}/{entity}/identify-mixed
The service returns the master record the draft would be matched into. No record is created or modified. Using the service requires authoring enabled and matching configured on the master layer. On a master view without master layer matching, the response is an empty array.
Unlike the identify service, the request body is a map of master attribute values, used as they are without cleansing. All keys must be master columns of the entity.
POST /master/masters/party/identify-mixed
{
"cmo_name": "John",
"cmo_integer": 4
}
The response is an array with the master record the draft would be matched into, or an empty array if there is no match. Matching proposals and match metadata are not returned for master-layer matching.
[
{
"record": {
"type": "party",
"metadata": {
"id": 90112,
"active": true
// more metadata
},
"attributes": {
"cmo_name": "John"
}
}
}
]
An attribute that does not exist or is not a master-origin column returns a 400 Bad Request HTTP status code.
An unknown master view or entity returns 404 Not Found.
Search
This service lets you search for records by attributes and values using a POST request.
For example, the following request searches for records with src_name values John or Paul and a std_age value 42:
POST /instance/party/search
{
"src_name" : ["John","Paul"],
"std_age" : 42
}
The request body is a map of column names to search values. Conditions are evaluated as follows:
| Search value | Behavior |
|---|---|
Multiple entries in the body |
Combined with AND. |
JSON array value |
OR within that column, for example, |
|
Matches records where the column has no value. |
String value containing |
Pattern match: |
String value without |
Exact, full-value match. |
Comma inside a string value |
Matched literally (unlike the GET request filters, where a comma separates OR values). |
Value for a non-string column |
The value is converted to the column type and compared for equality. |
The request supports the following parameters:
| Parameter | Description |
|---|---|
offset |
Used for paging. Offsets the first returned record, starts at 0. |
count |
When used alone or with |
caseSensitive |
When set to Case-insensitive matching does not use plain column indices.
For large tables, consider adding a functional index on |
The example request matches all records whose first name starts with ja in any casing, for example, James, Jane, or JANETTE.
POST /instance/party/search?caseSensitive=false
{
"src_first_name" : "JA*"
}
The response contains the matching records in the records array, each with type, metadata, and attributes.
Conditions are evaluated in the database.
An unknown column returns a 400 Bad Request HTTP status code.
So does a malformed sort value such as src_first_name ASC (a space instead of a colon), which is read as a column name.
An unknown entity or master view returns 404 Not Found.
Master search
You can also search for records on the master layer using a POST request.
The master search uses master column names and supports the same request body rules and the same offset, count, and caseSensitive query parameters as the instance search.
POST /master/{view}/{entity}/search
{
"cmo_first_name" : ["John","Paul"],
"cmo_age" : 42
}
Cleanse records
To run the data quality (DQ) cleansing configured for an entity, that is, normalizations and validations, on source attribute values without saving anything, use the following request:
POST /instance/{entity}/cleanse
The service returns the processed record, but no record is created or modified.
Records are cleansed in the same way as when they are processed, so the service can be used as a data quality firewall.
The request returns a 400 Bad Request HTTP status code if the entity has no cleanse action configured, the source system does not exist, record is missing, a key is not a source column of the entity, or a value cannot be converted to the column type.
An unknown entity returns 404 Not Found.
POST /instance/party/cleanse
{
"sourceSystem": "crm",
"record": {
"attributes": {
"src_first_name": " jane ",
"src_last_name": "WATSON",
"src_pid": "130 692 544",
"src_birth_date": "not-a-date"
}
}
}
The request body uses the following fields:
| Field | Required | Description |
|---|---|---|
sourceSystem |
Yes |
Name of the source system under which the record is interpreted. |
record.attributes |
Yes |
Source attribute values.
All keys must be source columns ( |
The response contains the parsed source values, the cleansed output values, and structured validation outcomes:
{
"record": {
"attributes": {
"source": {
"src_first_name": " jane ",
"src_last_name": "WATSON",
"src_pid": "130 692 544",
"src_birth_date": "not-a-date"
},
"clean": {
"std_first_name": "Jane",
"std_last_name": "Watson",
"std_pid": "130692544",
"std_gender": "F",
"exp_pid": "PID_REMOVED_SEPARATORS PID_VALID"
}
}
},
"validations": [
{
"column": "exp_birth_date",
"severity": "ERROR",
"message": "DATE_NOT_PARSED"
}
]
}
-
record.attributes.source: The non-null source values as parsed. Attributes sent asnullare omitted fromsource, and clean columns without a value are omitted fromclean. -
record.attributes.clean: The cleansed output columns produced by the cleanse action. -
validations: Structured DQ validation outcomes with the affected column, severity, and message. A column can contribute several entries (one per fired outcome code), and aggregate explanation columns (for example,exp_instance) repeat the codes of the columns they aggregate.
The DQ validation definitions for the validations field are by default loaded from the nme-validation.xml file.
If the file does not exist, the exp_* explanation columns are checked instead: the validations field then contains one entry for each outcome code found in these columns, with the code as the message and the severity always set to ERROR.
For details, see MDM Server Application Properties > MDM features.
Traverse master records
To follow relationships from a starting master record and return the related records, use the following request:
POST /master/{view}/{entity}/{id}/traverse
The request body carries a single traverse object in one of two modes:
| Mode | Request body | Result |
|---|---|---|
Traversal chain |
A |
The records reached by the last step of the chain. Intermediate steps are followed but not returned. |
Starting record with preloaded relationships |
A |
The starting record itself, with the preloaded relationships attached. |
An empty request body ({}) returns only the starting record.
Unknown fields in the request body are ignored.
The response has two fields: seedId, which repeats the ID of the starting record from the path, and records.
In both modes, the requested records are at the top level of the records field in the response, and the preloaded relationships are nested inside each record as relationships.
A record reached through several paths of the same relationship is returned only once.
The request structure follows these rules:
-
Every nested
traverseobject and everyrelationsentry must name its relationship inrelationName. Only the top-leveltraverseobject can omit it. An emptyrelationNameis rejected. -
A top-level object without
relationNamecan only carryrelations: afilteror a nestedtraverseobject on it is rejected. -
A
traverseobject is not allowed insiderelations. -
relationsis only allowed on the lasttraverseobject of a traversal chain. -
Request nesting and filter recursion are limited to 20 levels.
A request that violates these rules, names an unknown relationship, or exceeds the nesting limit returns a 400 Bad Request HTTP status code.
A nonexistent starting record returns 404 Not Found.
Traversal filters
Any traverse object or relations entry that names a relationship can carry a filter: a structured condition that selects which related records are returned.
{ "type": "EQ", "field": "src_name", "value": "Jack" }
| Condition type | Description |
|---|---|
|
Compares |
|
String pattern match with |
|
Combines the conditions in the nested |
|
Negates exactly one nested condition. |
Filter values are compared using the column type, so for example a DATETIME condition with the value 1984-06-04 00:00:00 matches the stored value 1984-06-04T00:00:00Z.
Filters are applied to the fetched records only (see Traversal limits).
Traversal examples
The following request returns the starting record together with its preloaded instances relationship, filtered:
POST /master/masters/party/76070/traverse
{
"traverse": {
"relations": [
{
"relationName": "instances",
"filter": { "type": "EQ", "field": "src_first_name", "value": "Jane" }
}
]
}
}
{
"seedId": 76070,
"records": [
{
"type": "party",
"metadata": {
"id": 76070
// more metadata
},
"attributes": {
"cmo_first_name": "Jannet"
// more attributes
},
"relationships": {
"instances": [
{
"attributes": {
"src_first_name": "Jane"
// more attributes
}
}
]
}
}
]
}
A filter that matches no records returns an empty array for that relationship.
The following request follows the contacts relationship and then the instances relationship of each contact, returning only the records reached by the last step (traversal chain):
POST /master/masters/party/76070/traverse
{
"traverse": {
"relationName": "contacts",
"traverse": { "relationName": "instances" }
}
}
To include the related records of the last-step records, list the relationships to preload in relations on the last traverse object of the chain.
Traversal limits
-
At most 10,000 related records are fetched per parent record at each chain step or preloaded relationship, and filters are applied to these records only. The endpoint does not support pagination.
-
LIKEconditions are case-sensitive. There is no case-insensitivity option on traversal filters. -
The caller’s entity, row, and column read permissions apply to the traversed records.
For the SOAP equivalent of this service, see Using Generic Traversal Master Service.
Read historical records
It is possible to get historical values of a record with a GET request.
| History endpoints are only available when the history plugin is used. See History Plugin for configuration details. |
| Endpoint | Description |
|---|---|
/history |
Returns the list of all historized entities. |
/instance/{entity}/history/metadata |
Returns the list of columns stored in the historized instance entity as configured in |
/instance/{entity}/{id}/history |
Returns historical instance records by the record id. |
/instance/{entity}/{origin}/{source_id}/history |
Returns historical instance records by origin and the record id. |
/master/{view}/{entity}/{id}/history |
Returns historical master records by the record id. |
/master/{view}/{entity}/history/metadata |
Returns the list of columns stored in the historized master entity as configured in |
Set the timeframe
Limit the number of results by specifying the from, to, or at parameters in the request.
The from and to parameters can be combined or used separately.
/master/masters/party/1734/history?from=2017-08-16T11:15:55Z&to=2017-08-25T11:15:55Z
[ {
"type" : "partymasters",
"metadata" : {
"id" : 1734,
"validFrom" : "2017-08-21T14:47:02Z",
"validTo" : "2017-08-24T14:48:11Z",
"active" : true
},
"attributes" : {
"cmo_type" : "P",
"cmo_first_name" : "John",
"cmo_last_name" : "Smith",
"cmo_gender" : "M",
"cmo_birth_date" : "1978-11-16T00:00:00Z",
"cmo_sin" : "95242433",
"dq_indicator" : 100000,
"dq_indicator_name" : "medium",
"group_size" : 2,
"published_by" : "admin"
}
}, {
"type" : "partymasters",
"metadata" : {
"id" : 1734,
"validFrom" : "2017-08-16T14:37:15Z",
"validTo" : "2017-08-21T14:47:02Z",
"active" : true
},
"attributes" : {
"cmo_type" : "P",
"cmo_first_name" : "J",
"cmo_last_name" : "Smith",
"cmo_birth_date" : "1978-11-16T00:00:00Z",
"cmo_sin" : "95242433",
"dq_indicator" : 111003,
"dq_indicator_name" : "medium",
"group_size" : 1,
"published_by" : "multiload"
}
} ]
Modify records
Mapping of HTTP methods to change type is as usual in REST:
-
Insert via POST (see POST request example).
-
Full update via PUT: attributes omitted from the request body are cleared (see PUT request example).
-
Partial update via PATCH: attributes omitted from the request body are preserved (see PATCH request example). Available for instance records only.
-
Deactivation or deletion via DELETE (see DELETE request example).
However, MDM can automatically adjust between create and update depending on whether the record is present in the MDM repository, that is, an attempt to update (PUT) a non-existing record is automatically changed to an insert operation (POST), and vice versa.
Record identification in requests
Records are identified by their id or a combination of origin and source_id (for instance records only).
This identification can be sent in the URI or in the request body.
PUT /instance/{entity}/{id}
POST /instance/{entity}/{origin}/{sourceId}
PUT/POST /master/{view}/{entity}/{id}
If {origin} contains a #, it must be escaped as %23 in the URI.
|
POST /instance/{entity}
{
"origin" : "crm#customer#party",
"source_id" : "cdr48"
}
All combinations of POST, PUT, PATCH, and DELETE requests and identification are supported to provide maximum integration flexibility.
The following variants return a 400 Bad Request HTTP status code:
-
Sending
idwhen creating a new record, as MDM generates its own IDs. -
Sending both
idandoriginwithsource_idin the request body. -
Repeating in the request body an identifier that is already in the URI.
Source timestamp formatting
In POST, PUT, and PATCH requests, the value of source_timestamp must comply with the ISO 8601 standard for date and time formats.
By default, Z is treated as local (server) time zone, not as UTC.
The time zone handling of REST API timestamps is controlled by the ataccama.one.mdm.nme.rest.timezone application property.
The default value legacy keeps the behavior described in this section: timestamps in responses are rendered in server-local time with a literal Z suffix, and Z-suffixed inputs are read as server-local time.
Setting the property to UTC, a zone ID (for example, Europe/Prague), or server switches the REST API to real offsets: timestamps in responses are rendered in the configured time zone with a correct offset, and an explicit Z or numeric offset on input timestamps is applied.
For details, see MDM Server Application Properties > MDM features.
Some of the supported formats are:
-
yyyy-MM-dd’T’HH:mm:ss’Z' -
yyyy-MM-dd’T’HH:mm:ss.SSS’Z' -
yyyy-MM-dd’T’HH:mm:ss -
yyyy-MM-dd’T’HH:mm:ss.SSS -
yyyy-MM-dd’T’HH:mm:ssZ
"2025-09-05T10:00:01Z"
"2025-09-05T10:00:02.345Z"
"2025-09-05T10:00:03"
"2025-09-05T10:00:05.678"
"2025-09-05T10:00:07+08:00"
In instance write request bodies, use sourceTimestamp for the source timestamp, the same name as in the record metadata of responses.
The source_timestamp spelling is also accepted.
If a request contains both, the last one is used.
Activate and deactivate records request example
Both instance and master records can be activated and deactivated repeatedly.
If the request is successful, the response contains a confirmation of the update.
Depending on the action, the recordChange can be:
-
INSERT: A new record was created. -
UPDATE: The record was updated (for example, the activity status was changed). -
DELETE: The record was deleted. -
NONE: No change was applied (for example, the record activity status remains the same). -
PURGE: The record was purged.
An unknown view or entity returns a 404 Not Found HTTP status code.
Instance layer
PUT /api/rest/instance/{entity}/{id}/activate
PUT /api/rest/instance/{entity}/{id}/deactivate
PUT /api/rest/instance/{entity}/{id}/remove-activity
{
"id": 74006,
"origin": "crm#customer#party",
"source_id": "100",
"recordChange": "NONE"
}
Master layer
PUT /api/rest/master/{view}/{entity}/{id}/activate
PUT /api/rest/master/{view}/{entity}/{id}/deactivate
PUT /api/rest/master/{view}/{entity}/{id}/remove-activity
{
"id": 159111,
"origin": null,
"source_id": null,
"recordChange": "UPDATE"
}
POST request example
Instance layer
POST /instance/party
{
"origin" : "crm#customer#party",
"source_id" : "cdr48",
"source_timestamp" : "2015-07-23T14:14:04Z",
"attributes" : {
"src_first_name" : "Johny",
"src_sin" : "547-954-624"
}
}
{
"result": "ok",
"records": {
"id": 4051,
"origin": "crm#customer#party",
"source_id": "cdr48-ase",
"recordChange": "INSERT"
"attributes": {
"master_id": 7560
}
}
}
The master_id attribute is included in the response from instance write endpoints.
You can enable this in the application.properties file (see MDM Features).
{
"origin" : "PAS#policyrole#party",
"source_id" : "6776",
"source_timestamp" : "2019-03-27T00:00:00Z",
"attributes" : {
"src_name_first" : "LINDA",
"src_name_last" : "CORRIE",
"src_name_middle" : "",
"src_gender" : "Female",
"src_date_of_birth" : ""
},
"relationships": {
"contact": [{
"source_id":"670",
"origin":"PAS#policyrole#contact",
"attributes": {
"party_source_id" : "671",
"src_value": "5354856",
"src_type" : "Home Phone"
}
}
]
}
}
When inserting a record with relationships via a POST request, you need to modify the Parent Role and Child Role in the MDM logical model according to what is defined in your request.
Alternatively, if you have no Parent or Child Role defined in the model, use rev_party_has_contact in place of contact in the request.
|
Master layer
POST http://localhost:8051/api/rest/master/masters/party
{
"attributes": {
"cmo_first_name": "rest3",
"cmo_sin": "12345"
},
"relationships": {
"addresses": [{
"attributes":{
"cmo_street": "ab1",
"cmo_city": "cd1"
}
},
{
"attributes":{
"cmo_street": "ab2",
"cmo_city": "cd2"
}
}]
}
}
{
"result": "ok",
"records": {
"id": 302003,
"recordChange": "INSERT",
"relationships": {
"addresses": [
{
"id": 302004,
"recordChange": "INSERT"
},
{
"id": 302005,
"recordChange": "INSERT"
}
]
}
}
}
PUT request example
Instance layer
PUT /instance/party/crm%23customer%23party/1001
{
"source_timestamp" : "2015-07-23T14:14:04Z",
"attributes": {
"src_first_name": "Dr. John",
"src_sin": "764-785-685"
},
"relationships": {
"id_documents": [{
"source_id":"pass-94515",
"origin":"crm#customer#id_document",
"attributes": {
"src_type" : "passport",
"src_value" : "489465498",
"party_source_id" : "1001"
}
}]
}
}
The central entity was updated, related entities were ignored since the data in the request was the same as before.
{
"result": "ok",
"records": {
"entity": {
"action": "UPDATED",
"id": 17603215,
"origin": "crm#customer#party",
"source_id": "12121212"
"attributes": {
"master_id": 7560
}
},
"relationships": {
"id_documents": {
"entity": {
"action": "NONE",
"id": 2207,
"origin": "crm#customer#id_document",
"source_id": "100_id_card_1"
}
}
}
}
}
The master_id attribute is included in the response from instance write endpoints.
You can enable this in the application.properties file (see MDM Features).
PATCH request example
A PATCH request partially updates an instance record: only the attributes present in the request body are modified, and omitted attributes keep their values. In contrast, a PUT request clears the attributes omitted from the request body.
PATCH requests are supported for instance records only, with all three ways of identifying the record:
PATCH /instance/{entity}
PATCH /instance/{entity}/{id}
PATCH /instance/{entity}/{origin}/{sourceId}
If a record identified by origin and source ID does not exist, it is created and the request returns a 201 Created HTTP status code with recordChange set to INSERT.
A PATCH request for a nonexistent internal id returns a 400 Bad Request HTTP status code instead, as internal IDs are generated by MDM.
An unknown relationship name in relationships also returns 400 Bad Request.
If the request changes nothing on the record, for example, because the sent values equal the current ones or only related records change, the response reports recordChange as NONE.
PATCH /instance/party/106667
{
"attributes": {
"src_last_name": "Patchedname"
}
}
{
"result": "ok",
"records": {
"id": 106667,
"origin": "crm#customer#party",
"source_id": "1001",
"recordChange": "UPDATE"
}
}
After the request, src_last_name is updated while all other attributes, such as src_first_name, keep their previous values.
The same request body sent via PUT would instead clear all omitted attributes.
Related-entity changes
Any instance write request (POST, PUT, PATCH, or DELETE) can carry a relationships map with child records that are processed together with the parent record in a single transaction.
In POST, PUT, and DELETE requests, child records are processed like the parent record: written by POST and PUT, deactivated or deleted by DELETE.
In PATCH requests, each child record, at any nesting depth, can have its own action set in the changeType field:
Child changeType |
Effect |
|---|---|
|
Write.
The child record is inserted if it is not found by |
|
Deactivate (soft delete).
The |
|
Deletion, with the same effect as DELETE with |
If a child record marked D or X carries its own relationships, the records nested under it are deactivated or deleted with it.
A nested record marked X under a parent marked D is deleted.
A single PATCH request can mix actions on child records as needed, for example, update one child record and delete another:
PATCH /instance/party/106667
{
"relationships": {
"contacts": [
{
"origin": "crm#contact#contact",
"source_id": "contact-1",
"changeType": "U",
"attributes": { "src_value": "updated@example.com" }
},
{
"origin": "crm#contact#contact",
"source_id": "contact-2",
"changeType": "X"
}
]
}
}
{
"result": "ok",
"records": {
"id": 106667,
"origin": "crm#customer#party",
"source_id": "1001",
"recordChange": "NONE",
"relationships": {
"contacts": [
{
"id": 107053,
"origin": "crm#contact#contact",
"source_id": "contact-1",
"recordChange": "UPDATE"
},
{
"id": 107054,
"origin": "crm#contact#contact",
"source_id": "contact-2",
"recordChange": "DELETE"
}
]
}
}
}
The changeType field is supported only on the child records of PATCH requests and on bulk delta items.
In other write requests, it is ignored like any other unknown field.
To deactivate or delete the parent record, use the DELETE method.
DELETE request example
Instance layer
MDM distinguishes three levels of record removal:
| Level | Effect | Visible in reads and searches | Reversible |
|---|---|---|---|
Deactivation (soft delete) |
The record is marked as inactive ( |
Yes, the record is still returned and flagged as inactive. |
Yes, the record can be activated again. |
Deletion |
The record is marked as deleted ( |
No |
Inserting a record with the same origin and source ID recreates it. |
Purge |
The record is removed from the database. |
No |
No. This is the only level that removes data. See Purge. |
By default, a DELETE request deactivates the instance record.
To delete the record instead, set the hard query parameter to true:
DELETE /instance/{entity}?hard=true
DELETE /instance/{entity}/{id}?hard=true
DELETE /instance/{entity}/{origin}/{sourceId}?hard=true
When the request body lists child records, they are removed at the same level as the parent record: with hard=true they are deleted, otherwise they are deactivated.
In the response, recordChange reflects the level: UPDATE for deactivation and DELETE for deletion.
A DELETE request with hard=true has the same effect as the change type X in bulk delta imports.
Use DELETE for a single record (or a record with its listed child records) and bulk delta for a batch of records of different entities.
DELETE http://localhost:8051/api/rest/instance/party/17603215
<empty-body>
{
"result": "ok",
"records": {
"id": 17603215,
"origin": "crm#customer#party",
"source_id": "12121212",
"recordChange": "UPDATE"
}
}
DELETE http://localhost:8051/api/rest/instance/party/17603215?hard=true
<empty-body>
{
"result": "ok",
"records": {
"id": 17603215,
"origin": "crm#customer#party",
"source_id": "12121212",
"recordChange": "DELETE"
}
}
After the request, the record no longer appears in reads or searches.
Master layer
Only authored master records can be deleted via the API. A DELETE request for these records deletes the record instead of deactivating it. For details, see Deletion strategy.
DELETE http://localhost:8051/api/rest/master/masters/party/302003
<empty-body>
{
"result": "ok",
"records": {
"id": 302003,
"recordChange": "DELETE"
}
}
Override interfaces
Instance records
Requests on the instance layer use the following parameters for record identification.
| Parameter | Description |
|---|---|
|
Instance entity name as defined in the model. |
|
ID of the record. |
You can use attributeName either in the URI or in the request body to specify one or more attributes involved in the request.
List record overrides
Use the following request to get the original value of the attribute before an override has been set. The request body is empty.
GET /instance/{entity}/{id}/override/{attributeName}
{
"recordType": "instance",
"entityType": "party",
"recordId": 1982,
"overrides": [
{
"attributeName": "src_first_name",
"value": "John"
}
]
}
Use the following request to get the list of all attributes with overrides and their values before the override has been set. The request body is empty.
GET /instance/{entity}/{id}/override
{
"recordType": "instance",
"entityType": "party",
"recordId": 1982,
"overrides": [
{
"attributeName": "src_first_name",
"value": "John"
},
{
"attributeName": "src_last_name",
"value": "Smith"
}
]
}
Set overrides
Use the following request to set an override on a particular attribute.
Specify the attributeName and value in the request body.
The response is empty.
PUT /instance/{entity}/{id}/override/{attributeName}
{
"overrides": [
{
"attributeName": "src_first_name",
"value": "John"
}
]
}
Use the following request to set overrides on several attributes.
Specify both the attributeName and value in the request body.
The response is empty.
PUT /instance/{entity}/{id}/override
{
"overrides": [
{
"attributeName": "src_first_name",
"value": "John"
},
{
"attributeName": "src_last_name",
"value": "Smith"
}
]
}
Delete overrides
Use the following request to delete an override on a particular attribute. Both the request and response body are empty.
DELETE /instance/{entity}/{id}/override/{attributeName}
Use the following request to delete all overrides currently set on a record. The response body is empty.
DELETE /instance/{entity}/{id}/override
You can optionally provide a request body to delete only specific overrides:
DELETE /instance/{entity}/{id}/override
{
"attributes": ["src_first_name", "src_last_name"]
}
Master records
Requests on the master layer use the following parameters for record identification.
| Parameter | Description |
|---|---|
|
Name of the master view. |
|
Master entity name as defined in the model. |
|
ID of the record. |
You can use attributeName either in the URI or in the request body to specify one or more attributes involved in the request.
List record overrides
Use the following request to get the original value of the attribute before an override has been set. The request body is empty.
GET /master/{view}/{entity}/{id}/override/{attributeName}
{
"recordType": "master",
"entityType": "party",
"recordId": 1982,
"overrides": [
{
"attributeName": "cmo_first_name",
"value": "John"
}
],
"viewName": "masters",
}
Use the following request to get the list of all attributes with overrides and their values before the override has been set. The request body is empty.
GET /master/{view}/{entity}/{id}/override
{
"recordType": "master",
"entityType": "party",
"recordId": 1982,
"overrides": [
{
"attributeName": "cmo_first_name",
"value": "John"
},
{
"attributeName": "cmo_last_name",
"value": "Smith"
}
],
"viewName": "masters",
}
Set overrides
Use the following request to set overrides on one or several attributes.
Specify both the attributeName and value in the request body.
The response is empty.
PUT /master/{view}/{entity}/{id}/override
{
"overrides": [
{
"attributeName": "cmo_first_name",
"value": "John"
},
{
"attributeName": "cmo_last_name",
"value": "Smith"
}
]
}
Delete overrides
Use the following request to delete an override on a particular attribute. Both the request and response body are empty.
DELETE /master/{view}/{entity}/{id}/override/{attributeName}
Use the following request to delete all overrides currently set on a record. The response body is empty.
DELETE /master/{view}/{entity}/{id}/override
You can optionally provide a request body to delete only specific overrides:
DELETE /master/{view}/{entity}/{id}/override
{
"attributes": ["cmo_first_name", "cmo_last_name"]
}
Manual match
To apply a batch of manual match operations, such as merging, splitting, isolating, or rematching records, use the following request:
POST /bulk/manual-match
The operations are applied in a single transaction: if any operation fails, none are applied.
An unknown entity, master view, or master entity returns a 404 Not Found HTTP status code and none of the operations are applied.
The request body carries an ordered operations array.
Each operation has a type field that determines which other fields are required:
| Type | Description | Required fields |
|---|---|---|
|
Moves master records into a target master record. |
|
|
Merges an instance record into target master records. |
|
|
Splits instance records out of their master group. |
|
|
Reruns matching for instance records. |
|
|
Reruns matching for a master record. |
|
|
Isolates a group from matching. |
|
|
Clears isolation on a group. |
|
The two merge operation types differ by direction:
-
In
MERGE_MASTER,targetMasterIdis the surviving master record andidslists the master records merged into it. -
In
MERGE_INSTANCE,idis the instance record being moved andtargetMasterIdsis a map of master ID column names to target master IDs. The map must cover exactly the master ID columns of the entity: an unknown column, a missing column, or anullvalue is rejected with a400 Bad RequestHTTP status code.
REMATCH and REMATCH_MASTER rerun matching from scratch: existing manual decisions (manual matches, splits, and resolved matching proposals) are discarded.
The rematch in the MDM Web App, by contrast, preserves them.
A record can be affected by at most one manual match operation in a single batch.
For example, ISOLATE_GROUP and UN_ISOLATE_GROUP operations with the same IDs cannot be combined in one request: run them as two consecutive requests instead.
Violating this rule fails the whole batch with a 500 Internal Server Error HTTP status code and nothing is applied.
POST /bulk/manual-match
{
"operations": [
{ "type": "MERGE_MASTER", "entity": "party", "viewName": "masters", "targetMasterId": 2, "ids": [1] },
{ "type": "MERGE_INSTANCE", "entity": "party", "id": 5, "targetMasterIds": { "master_id": 2 } },
{ "type": "SPLIT", "entity": "party", "ids": [3] },
{ "type": "REMATCH", "entity": "party", "ids": [6] }
]
}
The response contains one entry per affected record with its identification and the applied change.
Attribute values are not returned.
Records are listed in ascending order of id.
A single operation can affect several records: ISOLATE_GROUP and UN_ISOLATE_GROUP report every record of the group, and REMATCH_MASTER reports every instance record of the master record’s group.
If an operation results in no change, recordChange is NONE.
{
"result": "ok",
"records": [
{ "id": 1, "origin": "crm#customer#party", "source_id": "1", "recordChange": "UPDATE" },
{ "id": 3, "origin": "crm#customer#party", "source_id": "3", "recordChange": "UPDATE" },
{ "id": 5, "origin": "crm#customer#party", "source_id": "5", "recordChange": "UPDATE" },
{ "id": 6, "origin": "crm#customer#party", "source_id": "6", "recordChange": "NONE" }
]
}
An empty operations array is valid: the request returns a 200 OK HTTP status code with an empty records array and changes nothing.
Bulk delta imports
To import a batch of instance record changes for records of different entities, each with its own change type, in one database transaction, use the following request:
POST /bulk/instance/delta
If any item in the batch fails, nothing is saved.
The request body is a deltas array.
Each item uses the following fields:
| Field | Description |
|---|---|
|
Instance entity name. |
|
|
|
Attribute values.
The record is identified by |
|
Child-set synchronization per relationship name (see Child-set synchronization). |
The following rules apply:
-
A
DorXchange for a record that does not exist has no effect and is reported asrecordChange: "NONE". -
An
IorUchange for a deleted record recreates it. -
Sending the same record twice in one batch returns a
400 Bad RequestHTTP status code. So does an item withoutchangeTypeor without identification (id, ororiginwithsource_id). -
An unknown entity in any item returns a
404 Not FoundHTTP status code, and the whole batch is rolled back. -
The response contains one processed record per item, with the same
id,origin,source_id, andrecordChangefields as the single-record write responses, and child results nested underrelationships. Attribute values are not returned.
POST /bulk/instance/delta
{
"deltas": [
{
"entity": "party",
"changeType": "I",
"attributes": {
"source_id": "events-party-1",
"origin": "crm#customer#party",
"src_name": "Events Party"
}
},
{
"entity": "address",
"changeType": "I",
"attributes": {
"source_id": "multi-address-1",
"origin": "crm#address#address",
"party_source_id": "events-party-1",
"src_address": "Prague"
}
}
]
}
Child-set synchronization
Each item can carry a relationships map with a synchronization block per relationship name.
The block has the following fields:
-
mode: How the listed child records are applied.-
INCREMENT(default): Only the listed child records are inserted or updated. Unlisted child records are left untouched. -
FULL: The listed child records become the complete child set. Unlisted existing child records are removed according todeletionStrategy.
-
-
deletionStrategy: How unlisted child records are removed inFULLmode.-
DEACTIVATEorD(default): Removed child records are deactivated. -
DELETEorX: Removed child records are deleted.
-
-
records: The child records, each with itsattributesand, inINCREMENTmode, an optionalchangeType:I,U, or omitted write the child record,Ddeactivates it, andXdeletes it. Theattributessent withDorXare not written.In
FULLmode, a childchangeTypeis rejected with a400 Bad RequestHTTP status code, as the synchronization defines the removals.
A child record needs only its source_id and attribute values: the child origin and the foreign-key attribute are derived automatically from the relationship and the parent record.
Child records cannot nest further relationships as the synchronization is one level deep: such a request returns a 400 Bad Request HTTP status code.
For deeper trees, use PATCH requests with nested relationships instead.
Different relationships of one item can use different modes in the same request.
In this example, the listed address is updated and all other addresses of the parent record are deactivated.
Removed child records appear in the response with the change that was applied to them: UPDATE for deactivation or DELETE for deletion.
A FULL synchronization with an empty records array removes all child records of the parent record.
POST /bulk/instance/delta
{
"deltas": [
{
"entity": "party",
"changeType": "U",
"attributes": { "source_id": "events-party-1", "origin": "crm#customer#party" },
"relationships": {
"addresses": {
"mode": "FULL",
"deletionStrategy": "DEACTIVATE",
"records": [
{ "attributes": { "source_id": "events-addr-1", "src_address": "A1-updated" } }
]
}
}
}
]
}
Task management
Tasks have the following lifecycle statuses:
| Status | Description |
|---|---|
|
Task has been created but not yet started. |
|
Task is being worked on. |
|
Task resolution is being processed by the engine. |
|
Engine failed to apply the task resolution. Task can be retried. |
|
Task has been successfully resolved. |
|
Task was discarded without resolution. |
Tasks can have the following types:
| Type | Description |
|---|---|
|
Created when a record change requires manual review. |
|
Created for manual matching decisions. |
|
Created when the engine proposes a match that needs review. |
|
Created for new record creation workflows. |
|
General-purpose task type. |
Single task operations
Assign task
Use the following request to assign a task to a group of team members or one team member:
POST /api/rest/v2/tasks/{id}/assign
The request supports the following parameters:
| Parameter | Required | Description |
|---|---|---|
id |
Yes |
Task identifier. |
user |
No |
Name of a new user assignee. |
group |
No |
Name of a new group assignee. |
{
"id": 17,
"status": "NEW",
"name": "Resolve DQ issues",
"userAssignee": "jane.smith",
"groupAssignee": "MDM_viewer",
"workflowName": "consolidation",
"workflowStep": "draft",
"entityId": "contact.master.masters",
"created": "2022-12-09T17:56:23.359Z",
"createdBy": "jane.smith",
"lastEdited": "2023-08-03T06:32:51.538Z",
"lastEditedBy": "admin",
"type": "RECORD_CHANGE",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Click on record edit to fix DQ issues.",
"records": [
{
"id": 76628,
"entityId": "contact.master.masters"
},
{
"id": 76684,
"entityId": "contact.master.masters"
}
]
}
Get task detail
Use the following request to get task detail information (without comments and history):
GET /api/rest/v2/tasks/{id}
The request uses the following parameter:
| Parameter | Required | Description |
|---|---|---|
id |
Yes |
Task identifier. |
{
"id": 19,
"status": "IN_PROGRESS",
"name": "Missing PIDs",
"userAssignee": "rachel.adams",
"groupAssignee": "MDM_user",
"workflowName": "consolidation",
"workflowStep": "draft",
"entityId": "party.master.masters",
"created": "2022-12-09T17:58:33.517Z",
"createdBy": "jane.smith",
"lastEdited": "2023-08-02T19:28:46.761Z",
"lastEditedBy": "admin",
"type": "RECORD_CHANGE",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Click on record edit to start fixing DQ issues. You can also perform any other actions: add missing related data, activate or deactivate record, or split an instance from the master record.",
"records": [
{
"id": 76083,
"entityId": "party.master.masters"
},
{
"id": 76080,
"entityId": "party.master.masters"
},
{
"id": 76078,
"entityId": "party.master.masters"
}
]
}
Get task history
Use the following request to get history for a specific task:
GET /api/rest/v2/tasks/{id}/history
The request uses the following parameter:
| Parameter | Required | Description |
|---|---|---|
id |
Yes |
Task identifier. |
{
"history": [
{
"userName": "jane.smith",
"timeStep": "2022-12-09T16:55:45.897Z",
"action": "CREATE",
"step": null,
"reassign": null,
"comment": null,
"migrationResult": null,
"automatedTaskConfigId": null
},
{
"userName": "john.taylor",
"timeStep": "2022-12-09T17:08:29.717Z",
"action": "CREATE_DRAFT",
"step": null,
"reassign": null,
"comment": "ID: 8",
"migrationResult": null,
"automatedTaskConfigId": null
}
]
}
The action field in the task history can have the following values:
| Action | Description |
|---|---|
|
Task was created. |
|
Task was moved to a new workflow step. |
|
Task was resolved. |
|
Task was discarded. |
|
A comment was added. |
|
Task was reassigned to a different user or group. |
|
Task resolution failed. |
|
Task was loaded from an external source. |
|
Post-resolution action was executed. |
|
Task details were updated. |
|
A draft was created for the task. |
|
A draft was published. |
|
Draft publication failed. |
|
A draft was discarded. |
|
Task was migrated from a previous version. |
|
Task was created using automated task configuration. |
|
The automated task configuration that created this task was deleted. |
Get task comments
Use the following request to get comments for a specific task:
GET /api/rest/v2/tasks/{id}/comments
The request uses the following parameter:
| Parameter | Required | Description |
|---|---|---|
id |
Yes |
Task identifier. |
{
"comments": [
{
"userName": "jane.smith",
"timeStep": "2022-12-09T16:52:06.904Z",
"comment": "I think we need to get back to the product team to see how we can improve their data before they reach us"
}
]
}
Add task comment
Use the following request to add comments for a specific task:
POST /api/rest/v2/tasks/{id}/comments
The request uses the following parameter:
| Parameter | Required | Description |
|---|---|---|
id |
Yes |
Task identifier. |
POST /api/rest/v2/tasks/{id}/comments
Could you take a look at it, John?
{
"comments": [
{
"userName": "jane.smith",
"timeStep": "2023-08-03T06:15:48.127Z",
"comment": "Could you take a look at it, John?"
}
]
}
Bulk task operations
Create multiple tasks
Use the following request to create multiple tasks:
POST /api/rest/v2/tasks
POST /api/rest/v2/tasks
[
{
"type": "RECORD_CHANGE",
"name": "Missing PIDs",
"description": "Click on record edit to start fixing DQ issues.",
"records": [
{
"id": 56787,
"entityId": "party.master.masters"
}
],
"workflowName": "consolidation",
"workflowStep": "draft",
"userAssignee": "admin",
"groupAssignee": "MDM_user",
"severity": "LOW",
"linkAddress": "https://example.com/record/56787"
}
]
{
"createdTaskIds": [
36
]
}
The POST /v2/tasks endpoint returns HTTP 201 Created on success, not 200 OK.
|
You can add a clickable link field to the task description section in the task detail in MDM Web App.
To enable this, use the ataccama.one.mdm.task.link.enabled property (see Task configuration).
Update multiple tasks
Use the following request to update multiple tasks:
PATCH /api/rest/v2/tasks
PATCH /api/rest/v2/tasks
[
{
"taskId": 16,
"userAssignee": "jane.smith",
"groupAssignee": "MDM_viewer",
"severity": "LOW"
},
{
"taskId": 15,
"name": "Matching issue (address)"
}
]
{
"tasks": [
{
"id": 16,
"status": "IN_PROGRESS",
"name": "Matching issue",
"userAssignee": "jane.smith",
"groupAssignee": "MDM_viewer",
"workflowName": "consolidation",
"workflowStep": "draft",
"entityId": "party_proposal_k.match_proposal",
"created": "2022-12-09T17:55:45.897Z",
"createdBy": "jane.smith",
"lastEdited": "2023-08-04T09:56:32.002Z",
"lastEditedBy": "admin",
"type": "MATCHING_PROPOSAL",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Fix this matching issue",
"records": [
{
"id": 76108,
"entityId": "party_proposal_k.match_proposal"
},
{
"id": 76107,
"entityId": "party_proposal_k.match_proposal"
}
]
},
{
"id": 15,
"status": "IN_PROGRESS",
"name": "Matching issue (address)",
"userAssignee": "jane.smith",
"groupAssignee": "MDM_viewer",
"workflowName": "consolidation",
"workflowStep": "draft",
"entityId": "party_proposal_k.match_proposal",
"created": "2022-12-09T17:53:34.651Z",
"createdBy": "jane.smith",
"lastEdited": "2023-08-04T09:56:32.002Z",
"lastEditedBy": "admin",
"type": "MATCHING_PROPOSAL",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Different addresses",
"records": [
{
"id": 76111,
"entityId": "party_proposal_k.match_proposal"
},
{
"id": 76113,
"entityId": "party_proposal_k.match_proposal"
}
]
}
]
}
You can add a clickable link field to the task description section in the task detail in MDM Web App.
To enable this, use the ataccama.one.mdm.task.link.enabled property (see Task configuration).
Get tasks
Use the following request to get task details (without comments and history):
GET /api/rest/v2/tasks
The request supports the following parameters:
| Parameter | Required | Description |
|---|---|---|
active |
Yes |
Set to |
createdAfter |
No |
Filters tasks created after specified date (for example, |
createdBefore |
No |
Filters tasks created before specified date (for example, |
updatedAfter |
No |
Filters tasks updated after specified date (for example, |
updatedBefore |
No |
Filters tasks updated before specified date (for example, |
offset |
No |
Used for pagination. Defines how many items are skipped before returning results. |
page |
No |
Used for pagination.
Specifies the number of the page to return.
The number of records on each page is defined by |
count |
No |
Specifies the number of records included in the response. |
{
"tasks": [
{
"id": 19,
"status": "IN_PROGRESS",
"name": "Missing PIDs",
"userAssignee": "rachel.adams",
"groupAssignee": "MDM_user",
"workflowName": "consolidation",
"workflowStep": "draft",
"entityId": "party.master.masters",
"created": "2022-12-09T17:58:33.517Z",
"createdBy": "jane.smith",
"lastEdited": "2023-08-02T19:28:46.761Z",
"lastEditedBy": "admin",
"type": "RECORD_CHANGE",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Click on record edit to start fixing DQ issues. You can also perform any other actions: add missing related data, activate or deactivate record, or split an instance from the master record.",
"records": [
{
"id": 76083,
"entityId": "party.master.masters"
},
{
"id": 76080,
"entityId": "party.master.masters"
},
{
"id": 76078,
"entityId": "party.master.masters"
}
]
},
{
"id": 20,
"status": "NEW",
"name": "We need to fix this NPI!",
"userAssignee": null,
"groupAssignee": "MDM_user",
"workflowName": null,
"workflowStep": null,
"entityId": "facility.master.provider",
"created": "2022-12-09T18:06:35.521Z",
"createdBy": "john.taylor",
"lastEdited": "2022-12-09T18:06:35.521Z",
"lastEditedBy": "john.taylor",
"type": "RECORD_CHANGE",
"severity": "HIGH",
"automationDefinitionId": null,
"description": "Click on record edit to fix DQ issues.",
"records": [
{
"id": 81540,
"entityId": "facility.master.provider"
}
]
},
{
"id": 21,
"status": "NEW",
"name": "New record - Mark Dough",
"userAssignee": null,
"groupAssignee": "MDM_user",
"workflowName": null,
"workflowStep": null,
"entityId": "party.master.masters",
"created": "2022-12-09T18:12:08.253Z",
"createdBy": "john.taylor",
"lastEdited": "2022-12-09T18:12:08.253Z",
"lastEditedBy": "john.taylor",
"type": "CREATE",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Mark Dough, born 1973-09-16. I will just write down what I know",
"records": []
}
]
}
Get tasks for specific record
Use the following request to get tasks for a specific record:
GET /api/rest/v2/tasks/record/{recordId}
GET /api/rest/v2/tasks/record/{recordId}?entityId={entityId}
The request supports the following path and query parameters:
| Parameter | Required | Description |
|---|---|---|
recordId |
Yes |
Identifier of the MDM record (instance, master, or proposal) for which tasks are fetched. |
entityId |
No |
Identifier of the MDM entity for which tasks are fetched. |
{
"tasks": [
{
"id": 19,
"status": "IN_PROGRESS",
"name": "Missing PIDs",
"userAssignee": "rachel.adams",
"groupAssignee": "MDM_user",
"workflowName": "consolidation",
"workflowStep": "draft",
"entityId": "party.master.masters",
"created": "2022-12-09T17:58:33.517Z",
"createdBy": "jane.smith",
"lastEdited": "2023-08-02T19:28:46.761Z",
"lastEditedBy": "admin",
"type": "RECORD_CHANGE",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Click on record edit to start fixing DQ issues. You can also perform any other actions: add missing related data, activate or deactivate record, or split an instance from the master record.",
"records": []
},
{
"id": 33,
"status": "NEW",
"name": "Issue with PID on personal record",
"userAssignee": "",
"groupAssignee": "MDM_user",
"workflowName": "consolidation",
"workflowStep": "draft",
"entityId": "party.master.masters",
"created": "2023-03-20T22:27:56.395Z",
"createdBy": "admin",
"lastEdited": "2023-03-20T22:27:56.395Z",
"lastEditedBy": "admin",
"type": "RECORD_CHANGE",
"severity": "INTERMEDIATE",
"automationDefinitionId": 1,
"description": "Missing or invalid PID",
"records": []
}
]
}
Task workflow
Move task to a new step
Use the following request to move a task to a new workflow step; see Default master data workflow. To discard a task, see Discard task.
POST /api/rest/v2/tasks/{id}/move/{transition}
The request supports the following parameters:
| Parameter | Required | Description |
|---|---|---|
id |
Yes |
Task identifier. |
transition |
Yes |
Name of the transition, defined under GUI Configuration > Workflow Configuration (see Configuring Workflows). |
{
"id": 19,
"status": "IN_PROGRESS",
"name": "Missing PIDs",
"userAssignee": null,
"groupAssignee": "MDM_user",
"workflowName": "consolidation",
"workflowStep": "waiting_for_publish",
"entityId": "party.master.masters",
"created": "2022-12-09T17:58:33.517Z",
"createdBy": "jane.smith",
"lastEdited": "2023-08-04T10:29:46.101Z",
"lastEditedBy": "admin",
"type": "RECORD_CHANGE",
"severity": "LOW",
"automationDefinitionId": null,
"description": "Fix DQ issues.",
"records": [
{
"id": 76083,
"entityId": "party.master.masters"
},
{
"id": 76080,
"entityId": "party.master.masters"
},
{
"id": 76078,
"entityId": "party.master.masters"
}
]
}
Discard task
Use the following request to discard a specific task; see Discard task. The response is empty.
POST /api/rest/v2/tasks/{id}/discard
The request uses the following parameter:
| Parameter | Required | Description |
|---|---|---|
id |
Yes |
Task identifier. |
POST /api/rest/v2/tasks/{id}/discard
Task discarded comment
Lookups management
The lookups management endpoint triggers the same lookup synchronization as the Synchronize Lookups option in the MDM Web App Admin Center, so you can run it from scripts and pipelines. It is an Admin Center endpoint, so the REST API user role and permissions described in Authentication and authorization do not apply.
The endpoint is available only if lookup synchronization is enabled. This is controlled using the following property:
ataccama.one.mdm.lookup.storage.enabled=true
For details, see MDM Server Application Properties > Lookups management.
To access the endpoint, you need full access to the MDM Web App Admin Center (MDM_admin by default).
The REST API user role is not required.
See MDM Server Application Properties > MDM Admin Center permissions.
|
The endpoint checks the MinIO folder specified in the ataccama.one.mdm.lookup.storage.remote-prefix property (default value: ext/).
The folder needs to be present in both MinIO buckets (for upload and download).
Fetch lookup files
Use the following request to fetch lookup files from MinIO.
POST /manager/api/lookups/fetch
If successful, the response returns a confirmation that lookup files have been retrieved.
{
"name": "FetchLookups",
"scope": "CONFIGURATION",
"status": {
"state": "FINISHED",
"startedAt": "2025-08-15T05:22:21.221436328Z",
"finishedAt": "2025-08-15T05:22:21.27714669Z",
"errorMessage": null,
"errorTrace": null
}
}
The request supports the following query parameters:
| Parameter | Description |
|---|---|
overrideExistingFiles |
Set to Can be used together with |
deleteOrphanFiles |
Orphan files are files present in the local folder but not in a remote storage.
Set to Can be used together with |
POST /manager/api/lookups/fetch?overrideExistingFiles=true
POST /manager/api/lookups/fetch?deleteOrphanFiles=true
POST /manager/api/lookups/fetch?overrideExistingFiles=true&deleteOrphanFiles=true
Stream consumers
Use the following request to start the stream consumer {name}.
POST /api/rest/interfaces/streaming/consumers/{name}/start
Use the following request to stop the stream consumer {name}.
POST /api/rest/interfaces/streaming/consumers/{name}/stop
Use the following request to start all stream consumers.
POST /api/rest/interfaces/streaming/consumers/start
Use the following request to stop all stream consumers.
POST /api/rest/interfaces/streaming/consumers/stop
Purge
Purge removes records from the database. It is the only level of record removal that erases data (see DELETE request example). One endpoint serves two uses, selected by the request body:
POST /purge
| Use | Request body | Effect |
|---|---|---|
|
Runs the purge routine over obsolete and orphaned data. |
|
|
Removes the identified records and the related records selected for removal. |
A successful request returns a 200 OK HTTP status code with a JSON body.
Routine purge
Use the following request to initiate a housekeeping procedure.
The routine purge removes all records with eng_existing=0 whose deletion was already provided (that is, exported) in all configured incremental batch exports.
This also deletes matching proposals of the deleted records.
To check if record deletion was provided in an incremental batch export, you can compare the record deletion_tid and the batch export TREF values in the _EXPORT_REG table.
Record deletion has already been provided if deletion_tid is lower than TREF of batch exports.
Because of this, records that were deleted after executing some incremental batch export are not purged. To force purging of such records, you can provide the names of incremental batch exports that should be ignored in the request body.
POST /api/rest/purge
{"ignored": ["incrementalBatchExport1", "incrementalBatchExport2"]}
The response is {"result": "ok"}: the routine purge does not collect per-record information, so no counts are returned.
The operation is visible in the MDM Web App Admin Center under Orchestration > MD Process Monitoring > Data Statistics (see Administration).
Targeted purge
Use the targets field to remove specific records.
Each target contains either instance or master.
An instance target identifies an instance record by id or by origin and source_id (not both):
| Field | Description |
|---|---|
|
Instance entity name. |
|
Record identification. |
|
Relationship paths, separated by dots (for example, |
|
Instead of purging the instance record itself, locates the master records it belongs to (per |
A master target identifies a master record directly:
| Field | Description |
|---|---|
|
Master record identification.
The |
|
Master layer relationship paths whose records are purged together with the target record, each optionally with its own |
|
Relationship paths applied to the instance records of the master record, as in |
Purging a master record always takes all its instance records with it. Likewise, if all instance records of a master group are purged, their master record is purged as well to avoid orphan master records.
A target whose record does not exist is skipped and the request still succeeds, with "purgedCount": 0 in the response.
Identification errors, such as an unknown entity, view, or origin, are not skipped and fail the request with a 400 Bad Request HTTP status code.
POST /api/rest/purge
{
"targets": [
{ "instance": { "entity": "party", "id": "74001", "relationships": ["contacts"] } }
]
}
The response reports what was removed: purgedCount is the total number of purged records, including related records, and purged breaks the total down by layer and entity name.
{
"result": "ok",
"purgedCount": 5,
"purged": {
"instance": { "party": 1, "contact": 2 },
"master": { "party": 1, "contact": 1 }
}
}
In this example, the request removed the party record, its two contact instance records, and both master records that were left without instance records.
POST /api/rest/purge
{
"targets": [
{
"instance": {
"entity": "party", "origin": "crm#customer#party", "source_id": "1",
"masters": [ { "entity": "party", "viewName": "masters" } ]
}
}
]
}
In this example, the located master record is purged together with its instance records, including the one identified in the request.
A target that specifies both id and origin with source_id, neither or both of instance and master, or relationships together with masters returns a 400 Bad Request HTTP status code, as does an unknown entity, master view, or origin.
If the purge fails, the response is a 500 Internal Server Error with Purge failed in detail and an errorId.
Persistence
Get persistence layers
Use the following request to get information about all registered persistence layers and their LTC (Long Transaction Cleanup) statistics:
GET /api/rest/persistence
{
"persistence": [
{
"name": "vldb",
"ltcStats": {
"ltcCount": 42,
"timeSpent": "PT10M35S",
"transactionsCount": 1523,
"running": false,
"lastError": null
}
}
]
}
Index management
Use the following request to drop indices in VLDB persistences. If some indices were created or deleted manually, the operation fails.
DELETE /api/rest/persistence/indices
Use the following request to create indices in VLDB persistences. If some indices were created or deleted manually, the operation fails.
POST /api/rest/persistence/indices
Use the following request to start the LTC for all VLDB persistences.
POST /api/rest/persistence/triggerLtc
Use the following request to start the LTC for the VLDB persistence {name}.
POST /api/rest/persistence/{name}/triggerLtc
System parameters
Returns the currently set runtime parameters (see Runtime Parameters).
http://localhost:9090/api/rest/parameters
Source systems
Lists the source systems and information about them.
/source-systems
/source-systems/{name}
{
"sources": [
{
"name": "crm",
"uri": "http://localhost:8051/api/rest/source-systems/crm"
},
{
"name": "erp",
"uri": "http://localhost:8051/api/rest/source-systems/erp"
}
]
}
{
"name": "crm",
"origins": [
{
"name": "crm#customer#party",
"id": 1,
"entityName": "party",
"entityUri": "http://localhost:8051/api/rest/instance/party"
},
{
"name": "crm#customer#address",
"id": 2,
"entityName": "address",
"entityUri": "http://localhost:8051/api/rest/instance/address"
}
]
}
Tasks (system tasks)
Provides information about active and finished system tasks, the same as what is provided on the Task Execution screen in the MDM Web App Admin Center (see Monitoring).
Query parameters offset and count are not required; if they are not present, default values are used instead.
/tasks
/tasks?offset=0&count=5
/tasks/active
/tasks/active?offset=0&count=5
/tasks/finished
/tasks/finished?offset=0&count=5
/tasks/task/{id}
Cancel or stop system task
Cancels a queued system task (status WAITING) or stops a running system task (status RUNNING).
Depending on the initial status, the task then moves to CANCELING and then CANCELED, or to STOPPING and then STOPPED, respectively.
/tasks/task/{id}/terminate
curl -u {admin_username}:{admin_password} --basic {URL}/api/rest/tasks/task/{task_id}/terminate
Event handlers
Provides information about the event handlers, the same as what is provided on the Event Handlers tab in the MDM Web App Admin Center (see Interfaces).
Query parameters offset and count are not required; if they are not present, default values are used instead.
/event-handlers
/event-handlers?offset=0&count=5
/event-handlers/finished
/event-handlers/finished?offset=0&count=5
/event-handlers/finished/{id}
Event handler state
You can query and change the state of individual event handlers.
Get event handler state
Use the following request to get the current state of an event handler:
GET /api/rest/event-handlers/{name}/state
{
"state": "ACTIVE"
}
The state field can have the following values:
| State | Description |
|---|---|
|
Handler is processing events as expected. |
|
Handler is transitioning to active state. |
|
Handler is draining current events before becoming inactive. |
|
Handler is paused and not processing events. |
|
Handler is not configured or permanently turned off. |
Statistics
Shows various statistics regarding instance types, instance records, master views, and their records. The information is the same as what is provided under Orchestration > MD Process Monitoring > Data Statistics in the MDM Web App Admin Center (see Administration).
/statistics/instance
/statistics/master
Other interfaces
The following endpoints provide information about the MDM configuration:
-
Services: Lists the deployed native SOAP services and their endpoints.
-
Batch exports and batch loads: List the available batch operations.
-
Streaming consumers: Lists the configured streaming consumers with their name and status.
-
Operation plan: Shows the order in which the consolidation subtasks run in the MDM engine when loading or processing data (that is, cleansing, matching, and merging of specific entities).
/interfaces/services
/interfaces/batch/exports
/interfaces/batch/loads
/interfaces/streaming/consumers
/operation-plan
Invoke batch operations
Use the following requests to start a batch load or export operation by name. The API invokes the operations configured in the server configuration (see Batch Interface); it does not define them.
POST /interfaces/batch/loads/{name}
POST /interfaces/batch/exports/{name}
The optional request body is a flat string map of parameters passed to the operation, for example, {"param": "value"}.
The body can be omitted entirely or sent as {}: both start the operation with no parameters.
To start several load operations as a single task, use the multi-load request. The body names the operations and shares one parameter map:
POST /interfaces/batch/multiload
{
"operations": ["crm_delta", "erp_delta"],
"parameters": {}
}
The operations run asynchronously: a successful request returns a 202 Accepted HTTP status code with the ID of the started engine task.
The status code means the operation was accepted, not that it succeeded.
Track the task using the tasks endpoints.
{ "taskId": 528 }
An unknown operation name returns a 404 Not Found HTTP status code.
A multi-load request with duplicate operation names or an empty operations array returns a 400 Bad Request HTTP status code.
When a task fails, the failure reason is available only in the server log. The API exposes the state of the task but not the cause of the failure.
Operation plan
The operation plan shows the order of executing different consolidation subtasks in the MDM engine.
{
"plan": [
{
"name": "cleanse_party",
"provided": ["CLEANSED_party"],
"required": [],
"read": [
{ "name": "party", "uri": "http://localhost:8051/api/rest/instance/party" }
],
"written": [
{ "name": "party", "uri": "http://localhost:8051/api/rest/instance/party" }
]
},
{
"name": "match_party",
"provided": ["MATCHED_party"],
"required": ["CLEANSED_party"],
"read": [
{ "name": "party", "uri": "http://localhost:8051/api/rest/instance/party" }
],
"written": [
{ "name": "partymasters", "uri": "http://localhost:8051/api/rest/master/masters/party" }
]
}
]
}
SOAP to REST mapping
If you are migrating an integration from the SOAP services to the REST API, the following table maps the SOAP operations to their REST equivalents.
| SOAP | REST |
|---|---|
processMatchService ( |
The |
processDeltaService with change type |
|
|
PUT overwrites the whole record, as SOAP does. PATCH additionally offers a partial update, which SOAP does not have: omitted attributes are preserved. |
|
The |
|
The bulk delta |
|
|
processPurgeService (targeted purge, master entities, related records) |
A nonexistent record is skipped in REST (SOAP returns an error). See Targeted purge. |
|
|
listInstancesService and listMastersService (flat AND of equality and pattern conditions) |
REST additionally offers OR within a column via array values, sorting on list endpoints, and the |
|
|
genericTraversalMasterService ( |
The REST endpoint identifies the starting record by internal record ID only; origin and source ID are not supported. See Traverse master records. |
Batch invocation services ( |
|
Was this page useful?