On Monday 17 August 2026 24 August 2026, we will upgrade the Elasticsearch version used by our REST API. This is part of our regular maintenance of services and most users will not see any difference, however there are some important changes to pagination.
Cursors allow users to access large result sets and paginate through multiple pages of results. As part of the upgrade, we have made changes that make pagination more performant, but come with some limitations. The differences will only be noticed by a small number of users and are outlined in the following sections.
All request parameters required with a cursor
Currently, you can provide only a cursor as a parameter in followup requests — you don’t need all of the parameters provided in the first call. We have never documented this and we haven’t seen any evidence of users making requests in this way. Going forward, a cursor will only return the correct results when the same request parameters are used in every request.
A benefit is that cursors don’t expire, so you can come back and use the same cursor to pick up where you left off at any time in the future.
Workaround: Include all request parameters in all requests while using cursors.
If you make an initial request that looks like this:
https://api.crossref.org/works?filter=has-orcid:1&cursor=*
Your subsequent request should also include the same parameters with the cursor
https://api.crossref.org/works?filter=has-orcid:1&cursor=”nF1ZXJ5VGhlbkZldGNoJA…”
Changing result set
In the new implementation, the result set during cursor requests is not stable. This means that any changes made to records while retrieving multiple pages may lead to missing or duplicate records. The previous implementation was more resource-intensive and ensured a stable result set, but led to general instability of the API. We expect that very few request types will be affected, as most changes to record will not add or remove them from results sets.
The type of request most likely to be affected are those that use index date filters (from-index-date or until-index-date), this is because the index date is updated when a work is reindexed.
Workaround:
Reduce the size of results sets by splitting them into narrower time windows.
Verify that the number of results returned matches the total-count field found in the response to your first request: any difference may indicate that data has changed while you were making requests.
Where possible, use a stable date filter, such as from-created-date and until-created-date which will not change if another part of the record is updated. If you use the index date, avoid using from-index-date without until-index-date, to ensure that the very latest reindexed works don’t change the size of the result set.
Cursors and sorting
The new cursor implementation does not work well with sorting fields where the field does not always have a value defined. For this reason, we will not allow cursors to be combined with sorting by issued, published, published-print, or published-online. These requests will return a 400 response code.
Workaround: For smaller results sets, don’t use a cursor and use the maximum number of rows (1000). For larger results sets, use cursors without sorting and post-process the data to sort by the required field.
[Edit: the following case was added on 4 September]
Cursors change after every request
In the previous implementation of cursors, the same cursor was returned on every page of a large results set. This meant that it was possible to retrieve the cursor from only the first request, then reuse it for all of the following requests in the same results set. In the new implementation, the cursor is different for each page of results. We have always recommended that users retrieve the cursor on each result page, but some users may have made use of the cursor being the same each time and not updated it after every request. If you continue with that behaviour, you would keep re-collecting the same page.
Workaround: Make sure that you read from the next-cursor field after each request and update your cursor for the next request. As noted above, make sure you also include all of the original request parameters.
If you have any questions or feedback, let us you with a reply to this post.