How to use the PATCH record API operation
Introduction
The PATCH record API operation was introduced in API v4.9 to offer a method of performing partial modification on records. The examples provided in this article are for the latest API version (v6.13). The alternative HTTP PUT method should be used instead of PATCH when the intention is a complete replacement of a record.
The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI.
In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version.
The steps used to perform the PATCH operation are:
Select the record to update
Determine available operations for fields
Produce update xml
Perform operation
1: Select record to update
First, ensure that API imports are available for the source to which the record belongs. This can be confirmed using the GET /{cat}/sources resource and confirming the value api:importable is true (shown in bold).
<api:result>
<api:data-source category="publication" id="2147483646" name="c-inst-1">
<api:importable>true</api:importable>
<api:display-name>Local Source 1</api:display-name>
<api:precedence>
<api:type name="default" precedence-value="10"/>
<api:type name="reporting-tools" precedence-value="12"/>
<api:type name="herdc" precedence-value="13"/>
</api:precedence>
</api:data-source>
</api:result>Next, retrieve the record you wish to update using the GET /{cat}/records/{source-name}/{proprietary-id} resource. The following shows the truncated result of GET /publication/records/manual/ACF01DB4-72C8-4999-8931-63CD428C7D01 and contains a record of type 2 (book in this case) with fields: authors, keywords, pagination, and title.
...
<api:object category="publication" id="6926" last-modified-when="2012-10-10T12:03:11.55+01:00" href="https://localhost:8781/elements-api/v4.9/publications/6926" created-when="2012-07-12T15:22:26.57+01:00" type-id="2" type="book">
<!-- Publication type 2 is "book" -->
<api:ever-approved>true</api:ever-approved>
<api:reporting-date-1>1976-01-01</api:reporting-date-1>
<api:records>
<api:record format="native" source-id="1" source-name="manual" source-display-name="Manual" id-at-source="ACF01DB4-72C8-4999-8931-63CD428C7D01">
<api:verification-status>unverified</api:verification-status>
<api:native>
<api:field name="authors" type="person-list" display-name="Authors">
<api:people>
<api:person>
<api:last-name>Blundell</api:last-name>
<api:initials>TL</api:initials>
</api:person>
<api:person>
<api:last-name>Johnson</api:last-name>
<api:initials>LN</api:initials>
</api:person>
</api:people>
</api:field>
<api:field name="keywords" type="keyword-list" display-name="Keywords">
<api:keywords>
<api:keyword>Science</api:keyword>
<api:keyword>foo</api:keyword>
<api:keyword>bar</api:keyword>
</api:keywords>
</api:field>
<api:field name="pagination" type="pagination" display-name="Pagination">
<api:pagination>
<api:page-count>565</api:page-count>
</api:pagination>
</api:field>
<api:field name="title" type="text" display-name="Title">
<api:text>Protein crystallography</api:text>
</api:field>
</api:native>
</api:record>
</api:records>
...2: Determine Available Field Operations
There are up to four operations available for each field, these are:
SET: Available for all fields. The set operation will replace or add any existing field value with the provided field value.
CLEAR: Available for all fields. The clear operation will remove any existing field value.
ADD: Only available for list based fields. The add operation will add an item to an existing field or create a new field if none exists.
REMOVE: The remove operation will remove an item for an existing list of values. Only available for field types with identifiable items.
The following table shows available operations for each field type:
field | set | clear | add | remove |
|---|---|---|---|---|
academic-appointment-list | X | X | X | |
address-list | X | X | X | |
boolean | X | X | ||
certification-list | X | X | X | |
comment-list | X | X | X | X |
date | X | X | ||
decimal | X | X | ||
degree-list | X | X | X | |
funding-acknowledgements | X | X | ||
integer | X | X | ||
identifier-list | X | X | X | X |
issn-list | X | X | X | X |
keyword-list | X | X | X | X |
list | X | X | X | X |
money | X | X | ||
non-academic-employment-list | X | X | X | |
pagination | X | X | ||
person-list | X | X | X | |
person | X | X | ||
postgraduate-training-list | X | X | X | |
email-address-list | X | X | X | X |
text | X | X | ||
phone-number-list | X | X | X | X |
language-competency-list | X | X | X | X |
web-address-list | X | X | X | X |
embeddable-media-list (v5.20) | X | X | X | X |
Use the GET /{cat}/types resource to view the field type definitions and operations available. The following shows an example entry for the Book type returned by GET /publication/types with relevant information in bold.
...
<api:type id="2" name="book">
<api:heading-singular>Book</api:heading-singular>
<api:heading-plural>Books</api:heading-plural>
<api:heading-lowercase-singular>book</api:heading-lowercase-singular>
<api:heading-lowercase-plural>books</api:heading-lowercase-plural>
<api:fields>
<api:field>
<api:name>title</api:name>
<api:display-name>Title</api:display-name>
<api:type>text</api:type>
<api:is-mandatory>true</api:is-mandatory>
<api:update-field-operations>
<api:operation type="set" />
<api:operation type="clear" />
</api:update-field-operations>
</api:field>
<api:field>
<api:name>authors</api:name>
<api:display-name>Authors</api:display-name>
<api:type>person-list</api:type>
<api:is-mandatory>true</api:is-mandatory>
<api:update-field-operations>
<api:operation type="set" />
<api:operation type="clear" />
<api:operation type="add" />
</api:update-field-operations>
</api:field>
<api:field>
<api:name>pagination</api:name>
<api:display-name>Pagination</api:display-name>
<api:type>pagination</api:type>
<api:is-mandatory>false</api:is-mandatory>
<api:update-field-operations>
<api:operation type="set" />
<api:operation type="clear" />
</api:update-field-operations>
</api:field>
<api:field>
<api:name>keywords</api:name>
<api:display-name>Keywords</api:display-name>
<api:type>keyword-list</api:type>
<api:is-mandatory>false</api:is-mandatory>
<api:update-field-operations>
<api:operation type="set" />
<api:operation type="clear" />
<api:operation type="add" />
<api:operation type="remove" />
</api:update-field-operations>
</api:field> From the above XML operations by field:
title: set, clear
authors: set, clear, add
pagination: set, clear
keywords: set, clear, add, remove
3: Produce update XML
Now that we have the existing record data and the fields and operations available we can produce the update XML.
The following XML will perform the actions:
update the book title
add an author with and address
clear the pagination field
add notes field value
add a label
remove a label
<update-record xmlns="http://www.symplectic.co.uk/publications/api">
<fields>
<!--update the title-->
<field name="title" operation="set">
<text>Protein crystallography</text>
</field>
<!--add an author with an address-->
<field name="authors" operation="add">
<people>
<person>
<last-name>Coyote</last-name>
<initials>W.E.</initials>
<addresses>
<address>
<line type="full">The University of Acme</line>
</address>
</addresses>
</person>
</people>
</field>
<!--remove pagination-->
<field name="pagination" operation="clear"/>
<!--set the notes field-->
<field name="notes" operation="set">
<text>All this happened, more or less.</text>
</field>
<!--add an existing label. as the label is already present, nothing will be done-->
<field name="keywords" operation="add">
<keywords>
<keyword>foo</keyword>
</keywords>
</field>
<!--remove a label -->
<field name="keywords" operation="remove">
<text>Science</text>
</field>
</fields>
</update-record>To construct the update-record xml correctly, the please use the available API Schema mathcing the currently API endpoint version. It is recommended any constructed code be validated against the appropirate schema definition.
For example, the following element describes the pagination field:
<xs:complexType name="pagination">
<xs:sequence>
<xs:element name="begin-page" type="xs:string" minOccurs="0"/>
<xs:element name="end-page" type="xs:string" minOccurs="0"/>
<xs:element name="page-count" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>Which translates to (for example):
<field name="pagination" type="pagination">
<pagination>
<begin-page>11</begin-page>
<end-page>23</end-page>
<page-count>13</page-count>
</pagination>
</field>4: Perform operation
Use the /{cat}/records/{source-name}/{proprietary-id} resource with the PATCH verb. The headers need to include Authorization: basic and Content-Type:text/xml.
To update a record the API account must have write privileges, and if updating a user, HR access.
In our example, the URL is Patch /publication/records/manual/ACF01DB4-72C8-4999-8931-63CD428C7D01
If successful, a 200 (OK) response code will be returned and the response will contain the updated resource.
