REST API Scenarios
This article walks through common tasks that combine several REST API endpoints, from migrating a SOAP integration to removing a customer and all related data. For the description of the individual endpoints, parameters, and response fields, see REST API.
The scenarios use a demo model with the instance entity party (origin crm#customer#party), its relationships contacts and addresses, and the master view masters.
Record IDs are illustrative, so substitute your own values.
Responses are trimmed to the relevant fields.
Migrate a processDeltaService integration
An integration that writes records through the SOAP processDeltaService can switch to the REST API while keeping its record identification and attribute values. The SOAP change types map to REST requests as follows:
| SOAP change type | REST request |
|---|---|
|
For a partial update that keeps omitted attributes, which SOAP does not support, use PATCH instead. |
|
|
|
|
Child records |
The |
A batch of records of different entities |
|
For the full mapping of SOAP services, see REST API > SOAP to REST mapping.
The following steps show a typical sequence.
-
Create or update the record by origin and source ID. A PUT request overwrites the whole record like SOAP
IandU; the PATCH request used here changes only the sent attributes. A#in the origin is percent-encoded as%23in the path.PATCH /api/rest/instance/party/crm%23customer%23party/party-1 { "attributes": { "src_first_name": "Jane", "src_last_name": "Watson" } }If the record did not exist, the response returns a
201 CreatedHTTP status code withrecordChangeset toINSERT. On later calls, only the attributes in the body change andrecordChangeisUPDATE. -
Add child records in the same request as a parent update. Each child record selects its own action in
changeType.PATCH /api/rest/instance/party/crm%23customer%23party/party-1 { "attributes": { "src_first_name": "Jane" }, "relationships": { "contacts": [ { "origin": "crm#contact#contact", "source_id": "party-1-c1", "changeType": "I", "attributes": { "src_type": "email", "src_value": "jane@example.com", "party_source_id": "party-1" } } ] } }The response nests the child results under
relationships, each with its ownrecordChange. -
Delete the record and the listed child records in one transaction. The child records inherit the
hardparameter.DELETE /api/rest/instance/party?hard=true { "source_id": "party-1", "origin": "crm#customer#party", "relationships": { "contacts": [ { "source_id": "party-1-c1", "origin": "crm#contact#contact" } ] } }Every
recordChangein the response isDELETE. Without?hard=true, the same request deactivates the records instead, everyrecordChangeisUPDATE, and the records remain readable.
For details, see REST API > Modify records.
Keep child records in sync
When a source system sends a parent record together with its complete set of child records, for example, a customer with all current addresses, use a bulk delta import with child-set synchronization.
The mode of the synchronization decides what happens to child records that are not in the request.
-
Insert the parent with its child records. In
INCREMENTmode, only the listed child records are inserted or updated.The child origin and the foreign key to the parent record are derived from the relationship, so each child record needs only its
source_idand attributes.POST /api/rest/bulk/instance/delta { "deltas": [ { "entity": "party", "changeType": "I", "attributes": { "source_id": "party-2", "origin": "crm#customer#party", "src_name": "Events Party" }, "relationships": { "addresses": { "mode": "INCREMENT", "records": [ { "attributes": { "source_id": "addr-1", "src_address": "Prague 1" } }, { "attributes": { "source_id": "addr-2", "src_address": "Prague 2" } } ] } } } ] }The response mirrors the request: the parent with
recordChange: "INSERT"and both addresses nested underrelationships.addresses, each withrecordChange: "INSERT". -
Send the current child set in
FULLmode. The listed child records are inserted or updated, and every other existing child record is removed according todeletionStrategy.POST /api/rest/bulk/instance/delta { "deltas": [ { "entity": "party", "changeType": "U", "attributes": { "source_id": "party-2", "origin": "crm#customer#party" }, "relationships": { "addresses": { "mode": "FULL", "records": [ { "attributes": { "source_id": "addr-1", "src_address": "Prague 1, 110 00" } } ] } } } ] }The first address is updated, and the second address is deactivated because
deletionStrategydefaults toDEACTIVATE. Removed child records appear in the response withrecordChange: "UPDATE"for deactivation orDELETEfor deletion. -
Remove all child records by sending an empty
recordsarray inFULLmode.POST /api/rest/bulk/instance/delta { "deltas": [ { "entity": "party", "changeType": "U", "attributes": { "source_id": "party-2", "origin": "crm#customer#party" }, "relationships": { "addresses": { "mode": "FULL", "deletionStrategy": "DELETE", "records": [] } } } ] }Every remaining address is deleted and no longer appears in reads.
The synchronization is one level deep: child records cannot carry their own relationships.
For deeper trees, use PATCH requests with nested relationships instead.
See REST API > Bulk delta imports.
Follow a record through the change types
The change types I, U, D, and X move a record between three states: active, deactivated, and deleted.
The following sequence of bulk delta items for the same origin and source_id shows the effect of each step:
| Step | changeType |
Effect | recordChange in the response |
|---|---|---|---|
1 |
|
The record is created and active. |
|
2 |
|
The record is deactivated ( |
|
3 |
|
The record is reactivated and its attributes are updated. |
|
4 |
|
The record is deleted ( Inserting a record with the same origin and source ID recreates it. |
|
A D or X change for a record that does not exist has no effect and is reported as recordChange: "NONE".
The same states can be reached through single-record requests: a DELETE request deactivates the record, and DELETE with ?hard=true deletes it.
To erase a deleted record from the database, use a targeted purge.
See Remove a customer and all related data.
For the comparison of the three removal levels, see REST API > Modify records > DELETE request example.
Resolve duplicates with manual match
Manual match operations change how instance records are grouped into master records: a wrongly matched record is split out, two master records that represent the same real-world entity are merged, or records are rematched against the current rules. Several operations can be sent in one batch, which is applied in a single transaction.
The following batch splits one record out of its master group and merges two master records:
POST /api/rest/bulk/manual-match
{
"operations": [
{ "type": "SPLIT", "entity": "party", "ids": [1] },
{ "type": "MERGE_MASTER", "entity": "party", "viewName": "masters", "targetMasterId": 2, "ids": [3] }
]
}
The response lists every instance record that was affected, including the instance records of the merged master record:
{
"result": "ok",
"records": [
{ "id": 1, "origin": "crm#customer#party", "source_id": "1", "recordChange": "UPDATE" },
{ "id": 4, "origin": "crm#customer#party", "source_id": "4", "recordChange": "UPDATE" }
]
}
A record can be affected by at most one operation in a batch. Operations that depend on each other, such as isolating a group and then clearing the isolation on the same records, go into consecutive requests:
POST /api/rest/bulk/manual-match
{ "operations": [ { "type": "ISOLATE_GROUP", "entity": "party", "ids": [1] } ] }
POST /api/rest/bulk/manual-match
{ "operations": [ { "type": "UN_ISOLATE_GROUP", "entity": "party", "ids": [1] } ] }
To move a single instance record into a different master record, use MERGE_INSTANCE with the target master ID for every master ID column of the entity:
POST /api/rest/bulk/manual-match
{
"operations": [
{ "type": "MERGE_INSTANCE", "entity": "party", "id": 5, "targetMasterIds": { "master_id": 2 } }
]
}
To rerun matching for records after the matching rules changed, use REMATCH.
It discards the existing manual decisions on these records, so do not apply it to the records you split or merged in the earlier steps:
POST /api/rest/bulk/manual-match
{
"operations": [
{ "type": "REMATCH", "entity": "party", "ids": [7, 8] }
]
}
If the rematch changes nothing for a record, its recordChange is NONE.
For the operation reference, see REST API > Manual match.
Remove a customer and all related data
Removing a record completely, for example, to fulfill a data erasure request, takes the record through the three removal levels. Each level is a separate request, and you can stop at any of them.
-
Deactivate the record.
DELETE /api/rest/instance/party/crm%23customer%23party/party-3The record is flagged as inactive but still returned by reads and searches. To reverse this step, activate the record again.
-
Delete the record and its child records.
DELETE /api/rest/instance/party?hard=true { "source_id": "party-3", "origin": "crm#customer#party", "relationships": { "contacts": [ { "source_id": "party-3-c1", "origin": "crm#contact#contact" } ] } }The records no longer appear in reads or searches but remain in the database.
-
Purge the master record together with its instance records and the related records you select. Purging a master record removes all its instance records. The
masterRelationshipsandinstanceRelationshipsfields add related records by relationship path.POST /api/rest/purge { "targets": [ { "master": { "entity": "party", "viewName": "masters", "id": "76083", "masterRelationships": [ { "name": "contacts", "instanceRelationships": ["contact_infos"] } ], "instanceRelationships": ["contacts"] } } ] }The response counts every removed record by layer and entity:
{ "result": "ok", "purgedCount": 5, "purged": { "instance": { "party": 1, "contact": 2 }, "master": { "party": 1, "contact": 1 } } }Master records left without instance records are removed as well and included in the counts. A target whose record no longer exists is skipped, so repeating the request is safe.
If you only know the instance record, target it instead and set masters to purge the master records it belongs to.
For details, see REST API > Purge > Targeted purge.
Read related data with traversal
Traversal returns records related to a starting master record over one or more relationships, with the related records of the result attached as preloaded relationships.
The following requests start from the master record 76070 of the party entity.
To return the starting record with its instance records attached, send a traverse object without relationName and list the relationships to preload in relations:
POST /api/rest/master/masters/party/76070/traverse
{
"traverse": {
"relations": [ { "relationName": "instances" } ]
}
}
The response contains the starting record with the preloaded instance records:
{
"seedId": 76070,
"records": [
{
"type": "party",
"metadata": { "id": 76070 },
"attributes": { "cmo_first_name": "Jannet" },
"relationships": {
"instances": [
{ "attributes": { "src_first_name": "Jane" } },
{ "attributes": { "src_first_name": "Jannet" } }
]
}
}
]
}
To return the records reached over a relationship instead, name it in relationName.
Preloaded relationships are allowed on the last step of the chain only, so the following request returns the contacts of the party, each with its instance records attached:
POST /api/rest/master/masters/party/76070/traverse
{
"traverse": {
"relationName": "contacts",
"relations": [ { "relationName": "instances" } ]
}
}
To narrow down the result, add a filter to any traverse object or relations entry that names a relationship.
The following request returns only the instance records whose first name is Jane:
POST /api/rest/master/masters/party/76070/traverse
{
"traverse": {
"relations": [
{ "relationName": "instances", "filter": { "type": "EQ", "field": "src_first_name", "value": "Jane" } }
]
}
}
For the request rules, the filter conditions, and the limits, see REST API > Traverse master records.
Was this page useful?