Skip to content
SharePoint Integration

The SharePoint REST API in Practice

Endpoints, query options, request digests and the mistakes that turn a working integration into a slow or broken one.

Rajiv KumarApril 13, 20204 min read
SharePoint REST API Diagram

A practical guide to the SharePoint REST API: why $select is not optional, how paging really works, what a request digest is for, and why anything built on ACS authentication stopped working in April 2026.

The SharePoint REST API is what you use when the platform's own tools do not fit — a custom integration, an external system that needs to read a list, a script in a language with no SharePoint SDK. It is well documented and mostly predictable, and the parts that catch people out are consistent enough to be worth knowing in advance.

The shape of the API

Every endpoint hangs off a site's _api path:

https://contoso.sharepoint.com/sites/finance/_api/web/lists/getbytitle('Invoices')/items

Three things are always true and worth internalising:

  • The site in the URL scopes the request. There is no tenant-wide list query; you address one site at a time.
  • Ask for JSON explicitly. Without an Accept header you may get XML.
  • Reads are GET; writes need more. Creating and updating requires a request digest and the correct headers.

Reading data

The query options that matter, and the one that matters most:

GET /_api/web/lists/getbytitle('Invoices')/items
    ?$select=Id,Title,Amount,Status,Created
    &$filter=Status eq 'Approved'
    &$orderby=Created desc
    &$top=100
Accept: application/json;odata=nometadata

$select is not optional in practice. Omit it and SharePoint returns every column on every item, including ones you did not know existed. On a wide list that is a large multiple of the payload you need. Naming columns explicitly is the single most effective thing you can do for performance.

odata=nometadata is similarly worth setting. It strips OData metadata you almost certainly are not using and makes responses substantially smaller and easier to read.

Expanding lookups

Lookup and person columns return an ID by default. To get the related values, expand them — and note that $select must name the expanded fields too:

GET /_api/web/lists/getbytitle('Invoices')/items
    ?$select=Id,Title,Author/Title,Author/EMail
    &$expand=Author

Paging

The list view threshold applies to the API exactly as it does to the interface. Rather than constructing your own paging, follow the odata.nextLink the response provides — it encodes the paging state correctly, including for filtered queries.

Writing data

Writes need a request digest, which proves the request came from an authorised context.

POST /_api/contextinfo
Accept: application/json;odata=nometadata

Take FormDigestValue from the response and send it with the write:

POST /_api/web/lists/getbytitle('Invoices')/items
Accept: application/json;odata=nometadata
Content-Type: application/json;odata=verbose
X-RequestDigest: <FormDigestValue>

{
  "__metadata": { "type": "SP.Data.InvoicesListItem" },
  "Title": "INV-2043",
  "Amount": 1250.00,
  "Status": "Draft"
}

The __metadata.type value is the list's entity type name. It is derived from the list's internal name, not its display title, so a list renamed after creation keeps its original entity type. Read it from /_api/web/lists/getbytitle('Invoices')?$select=ListItemEntityTypeFullName rather than guessing.

Updates and deletes additionally need IF-MATCH and an X-HTTP-Method override:

POST /_api/web/lists/getbytitle('Invoices')/items(42)
X-RequestDigest: <FormDigestValue>
IF-MATCH: *
X-HTTP-Method: MERGE

IF-MATCH: * means "update regardless of version". Where concurrent edits are possible, send the item's actual ETag instead so a conflicting update fails rather than silently overwriting.

Authentication

For anything outside a SharePoint page, register an application in Microsoft Entra ID and authenticate with OAuth 2.0. Azure ACS-based authentication was retired for SharePoint Online in April 2026, so approaches built on appregnew.aspx registrations no longer work.

For new integrations, evaluate Microsoft Graph first. Graph covers a growing share of SharePoint functionality with a more consistent interface. The SharePoint REST API remains necessary for scenarios Graph does not yet reach, which is why both are worth knowing.

Common mistakes and better practice

  • Omitting $select. The most common performance problem, and the easiest to fix.
  • Constructing paging manually. Follow odata.nextLink; hand-built $skip paging misbehaves on filtered queries.
  • Ignoring the view threshold. The API is subject to it too. Index the columns you filter on.
  • Guessing the entity type name. Read ListItemEntityTypeFullName; renamed lists keep their original internal name.
  • Using IF-MATCH: * everywhere. Fine for single-writer automation, wrong where concurrent edits happen.
  • Building on retired authentication. ACS is gone. Use Entra ID.
  • One request per item. For bulk work, use $batch rather than a loop of individual calls.

Troubleshooting

ResponseCauseResolution
401 UnauthorizedToken missing, expired, or issued by retired ACSAuthenticate through Entra ID and refresh the token
403 Forbidden on write, reads workMissing request digest, or insufficient permissionFetch /_api/contextinfo and send X-RequestDigest
400 with an entity type error__metadata.type does not match the listRead ListItemEntityTypeFullName from the list
Threshold error on a filtered queryFilter column not indexedIndex the column; keep result sets small
Lookup fields return only an IDNot expandedAdd $expand and select the child fields
429 Too Many RequestsThrottlingHonour Retry-After; batch requests; set a descriptive User-Agent
Update overwrote another user's changeIF-MATCH: *Send the item's ETag instead

Frequently asked questions

REST API or Microsoft Graph?

Graph first for new work where it covers the scenario — it is more consistent and more actively extended. The SharePoint REST API remains necessary for functionality Graph does not yet expose.

Why do writes fail when reads succeed?

Almost always the request digest. Reads do not need it; writes do.

Does the 5,000 item threshold apply to the API?

Yes. It is a platform limit, not an interface limit.

How should throttling be handled?

Honour the Retry-After header, back off rather than retrying immediately, batch where possible, and set a descriptive User-Agent so the service can identify your traffic.

Can ACS-based authentication still be used?

No. Azure ACS was retired for SharePoint Online in April 2026. Applications must use Microsoft Entra ID.

The parts worth getting right

Most REST API difficulty comes down to four things: select your columns, follow the provided paging link, fetch a digest before writing, and authenticate through Entra ID.

Get those right and the API is unremarkable to work with. Skip any of them and you get a slow integration, a paging bug, a 403 you cannot explain, or an integration that stopped working in April 2026.

Share