SharePoint List REST API. Part 1

Common operations with SharePoint List and Document Library described here: Working with lists and list items with REST. In this post, I'll show how to perform operations with most of the existing field types such as Metadata (Taxonomy), MultiChoice, Lookup, and others.

List Fields

Our demo list contains the following fields:

Demo list fields

Demo list fields

The only Title field is required.

Before we begin to work with SharePoint REST API here is a couple of things about the environment:

Sample AJAX request:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Accept": "application/json; charset=utf-8",
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val()
    }
});

X-RequestDigest header must contain valid digest for each non-GET REST request Work with __REQUESTDIGEST.

To get REST url for list you can use this code:

var url = _spPageContextInfo.webServerRelativeUrl + "_api/web/lists/getbytitle('" + listTitle + "')"

List Item EntityType FullName

To interact with data stored in a list or document library we have to know the full name of the entity. To retrieve it from the list you can use following GET-request:

var url = _spPageContextInfo.webServerRelativeUrl + "_api/web/lists/getbytitle('" + listTitle + "')?$select=ListItemEntityTypeFullName"

And the response will contain value what we need:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <id>https://{YOUR_TENANT_NAME}.sharepoint.com/_api/Web/Lists(guid'{YOUR_LIST_ID}')</id>
    <category term="SP.List" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <link rel="edit" href="Web/Lists(guid'{YOUR_LIST_ID}')" />
    <content type="application/xml">
        <m:properties>
            <d:ListItemEntityTypeFullName>SP.Data.CRUDListListItem</d:ListItemEntityTypeFullName>
        </m:properties>
    </content>
</entry>

In my case entity name equals SP.Data.CRUDListListItem.

So we have all we need to begin: digest from hidden field, list name which we know, web server relative url from _spPageContextInfo object and ListItemEntityTypeFullName property value.

Let's start with the simple and will move step-by-step to complex. In all examples I'll show four operations: Create, Read, Update, and Delete.

Single line of text/Multiple lines of text

The simplest case for us definitely is text fields.

Create

To add new item we have to perform POST-request which contains digest:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- digest
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "Title": "TextFieldValue" // <-- "field internal name": "field value"
    })
});

The server response in case of successful completion of the operation will be properties of the newly created item and the status HTTP 201 Created:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <content type="application/xml">
        <m:properties>
            <d:Id m:type="Edm.Int32">3</d:Id>
            <d:Title>TextFieldValue</d:Title>
        </m:properties>
    </content>
</entry>

The response contains item identity which we will use to retrieve the data.

Read

To read property value we have to know list item ID and internal property name. Request to get the item from server:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)?$select=Title", // <-- list item id
    type: "GET",
    headers: {
        "Content-Type": "application/json;odata=verbose"
    }
});

Update

Update request must contain two special headers: X-HTTP-Method and IF-MATCH:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)", // <-- list item id
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val(), // <-- digest
        "X-HTTP-Method": "MERGE", // <-- for update request
        "IF-MATCH": "*" // <-- for update request
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "Title": "NewFieldValue" // <-- "field internal name": "field value"
    })
});

Response for update request has status 304 No Content.

All fields must be transferred to Update request?

No, only the fields you need to update. Fields not presented in the request will not be affected.

Delete

Set value to null to clear field value.

$.ajax({
    // rest parameters of the request
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "Title": null // <-- clear field value
    })
});

Choice

Create

There is a choice field in my list and "fill-in" option is disabled:

Choice field

Choice field

And the first Create request with expected value for the choice field:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- digest
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "SingleChoiceField": "Choice 1" // <-- "field internal name": "field value"
    })
});

And new item in the list:

Please pay attention to the behavior of SharePoint:

SharePoint REST API allows create and update items with no values in the required fields!

Read

See read section for text field.

Update

For update request I try to set not valid value for the choice field:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)", // <-- list item id
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val(), // <-- digest
        "X-HTTP-Method": "MERGE", // <-- for update request
        "IF-MATCH": "*" // <-- for update request
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "SingleChoiceField": "NotValidValue" // <-- "field internal name": "field value"
    })
});

As you can see validation is up to you in case of using SharePoint REST API:

Delete

See delete section for text field.

MultiChoice

Interaction with text and choice fields is very similar. But in the case of a multi-choice field, there are a couple of things to keep in mind.

Create

Multi choice field value unlike single choice must be presented as Collection(Edm.String) object:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- digest
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "MultiChoiceField": {
                "__metadata": {"type": "Collection(Edm.String)"},
                "results": [ // <-- array of values
                        "Choice 1",
                        "Choice 2"
                ]
        }
    })
});

Read

GET-request

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)?$select=MultiChoiceField", // <-- list item id
    type: "GET",
    headers: {
        "Content-Type": "application/json;odata=verbose"
    }
});

And the response contains array of values:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <category term="SP.Data.CRUDListListItem" />
    <content type="application/xml">
        <m:properties>
            <d:MultiChoiceField m:type="Collection(Edm.String)">
                <d:element>Choice 1</d:element>
                <d:element>Choice 2</d:element>
            </d:MultiChoiceField>
        </m:properties>
    </content>
</entry>

Update

Another one valid request containing not valid values for multi choice field:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)", // <-- list item id
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val(), // <-- digest
        "X-HTTP-Method": "MERGE", // <-- for update request
        "IF-MATCH": "*" // <-- for update request
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "MultiChoiceField": {
                "__metadata": {"type": "Collection(Edm.String)"},
                "results": [ // <-- array of values
                        "NotValidValue 1",
                        "NotValidValue 2"
                ]
        }
    })
});

Delete

See delete section for text field.

Single Lookup/User Field

The user field is based on the lookup field. Therefore both of these field types work similarly in the REST API context.

Create

Working with lookup field we can pass only identifiers into request. The field name in the request is Id. Just append "Id" after field name:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- digest
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "SingleLookupId": 1 // <-- lookup item ID
    })
});

Read

To retrieve lookup or user field value you can use Id pseudo field to get Id of lookup item. To get full lookup item Id and lookup field you have to pass $expand query parameter:

var restUrl = "/_api/web/lists/getbytitle('CRUDList')/items(3)?"+
    "$select=SingleLookupId,SingleLookup/Id,SingleLookup/Title&"+ // <-- select id and projected fields
    "$expand=SingleLookup"; // <-- expand lookup field
$.ajax({
    url: restUrl,
    type: "GET"
});

And the response for this request:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <link title="SingleLookup">
        <m:inline>
            <entry>
                <content type="application/xml">
                    <m:properties>
                        <d:Id m:type="Edm.Int32">2</d:Id>
                        <d:Title>Item 2</d:Title>
                    </m:properties>
                </content>
            </entry>
        </m:inline>
    </link>
    <content type="application/xml">
        <m:properties>
            <d:SingleLookupId m:type="Edm.Int32">2</d:SingleLookupId>
        </m:properties>
    </content>
</entry>

Update

Update request is similar to Create one. Just add item Id and the header values.

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- digest
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "SingleLookupId": 1 // <-- lookup item ID
    })
});

Delete

See delete section for text field.

Multi Lookup/User Field

The multi lookup field in the create and update requests must be presented as an array of lookup items' identifiers.

The name of the multi lookup field also must contain Id postfix.

Create

Array of lookup items' identifiers as a value of multi lookup field:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- digest
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- entity type name
        "MultiLookupId": {
                "results": [1, 2, 3]  // <-- lookup item ID
        }
    })
});

Read

var restUrl = "/_api/web/lists/getbytitle('CRUDList')/items(3)?"+
    "$select=MultiLookupId,MultiLookup/Id,MultiLookup/Title&"+ // <-- select id and projected fields
    "$expand=MultiLookup"; // <-- expand lookup field
$.ajax({
    url: restUrl,
    type: "GET"
});

The response contains array of identifiers and array of objects with projected fields:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <link title="MultiLookup">
        <m:inline>
            <feed>
                <entry>
                    <content type="application/xml">
                        <m:properties>
                            <d:Id m:type="Edm.Int32">1</d:Id>
                            <d:Title>Item 1</d:Title>
                        </m:properties>
                    </content>
                </entry>
                <entry>
                    <content type="application/xml">
                        <m:properties>
                            <d:Id m:type="Edm.Int32">2</d:Id>
                            <d:Title>Item 2</d:Title>
                        </m:properties>
                    </content>
                </entry>
                <entry>
                    <content type="application/xml">
                        <m:properties>
                            <d:Id m:type="Edm.Int32">3</d:Id>
                            <d:Title>Item 3</d:Title>
                        </m:properties>
                    </content>
                </entry>
            </feed>
        </m:inline>
    </link>
    <content type="application/xml">
        <m:properties>
            <d:MultiLookupId m:type="Collection(Edm.Int32)">
                <d:element>1</d:element>
                <d:element>2</d:element>
                <d:element>3</d:element>
            </d:MultiLookupId>
        </m:properties>
    </content>
</entry>

Update

Update request is similar to Create one for a multi lookup field. Just add item Id and the header values.

Delete

See delete section for text field.

The rest of the field types such as Metadata, Hyperlink, and others will be in the second part of this post.

Vitaly Zhukov

Vitaly Zhukov

Tech Lead, Architect, Developer, Technical Trainer, Microsoft MVP. Over 20 years of experience in system integration and software development. I specialize in designing and implementing scalable, high-performance software solutions across various industries.

You May Also Like

Call Dataverse API from SPFx Web Part

Call Dataverse API from SPFx Web Part

Provision Lists and Libraries with SPFx solution

Provision Lists and Libraries with SPFx solution

SharePoint. Drag-and-Drop File Uploading

SharePoint. Drag-and-Drop File Uploading

CSOM. Upload document

CSOM. Upload document

SharePoint List REST API. Part 2

SharePoint List REST API. Part 2

SharePoint Framework. Create Angular WebPart

SharePoint Framework. Create Angular WebPart

Project Server. CSOM + Custom Fields

Project Server. CSOM + Custom Fields

SharePoint 2010. Long time operation with updatable status

SharePoint 2010. Long time operation with updatable status

Linq to SharePoint. Cross site collection queries

Linq to SharePoint. Cross site collection queries

SharePoint. Getting Document Icon URL

SharePoint. Getting Document Icon URL

Linq to SharePoint. Repository pattern

Linq to SharePoint. Repository pattern

Linq to SharePoint vs Camlex.NET Performance Comparison

Linq to SharePoint vs Camlex.NET Performance Comparison

Linq to SharePoint. Part 5. Choice and MultiChoice fields

Linq to SharePoint. Part 5. Choice and MultiChoice fields

Linq to SharePoint. Part 4

Linq to SharePoint. Part 4

Linq to SharePoint. Part 3

Linq to SharePoint. Part 3

Linq to SharePoint. Part 2

Linq to SharePoint. Part 2

Linq to Sharepoint. Part 1

Linq to Sharepoint. Part 1