I'm calling a REST API that returns a maximum of 25 items per request. The response includes a cursor for pagination: the first response has only an `after` cursor, middle responses have both `before` and `after`, and the final response has only `before`. I want to keep requesting the next page until there is no `after` cursor left, while collecting every item into one list.
My current script makes the initial request, then enters a `do/while` loop. However, I'm having trouble updating the request URI with the newest cursor and keep risking an infinite loop. What is the correct PowerShell pattern for updating the cursor and continuing until the API stops returning an `after` value?
4 Answers
You can also avoid manually concatenating the cursor if the API returns a complete next-page URL. Some APIs provide pagination links directly in the response. If it does not, the same `do/until` pattern works: fetch a page, append its items, set the next cursor, and stop when the cursor is null or empty.
Use the response from the current iteration to build the next request. Keep the base URI unchanged, update the response variable each time, and test the new response’s `after` cursor. For example:
```powershell
$baseUri = 'https://api.domain.com/items?per_page=25'
$allItems = @()
$response = $null
do {
$uri = if ($response.result_info.cursors.after) {
"$baseUri&cursor=$($response.result_info.cursors.after)"
} else {
$baseUri
}
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
$allItems += $response.result
} while ($response.result_info.cursors.after)
```
The important part is that `$response` is replaced with the latest response before the loop condition is checked. Otherwise, every iteration can keep using the original cursor.
Also watch the string delimiters. In PowerShell, variables are expanded inside double-quoted strings, not ordinary single-quoted strings. Use something like `"$baseUri&cursor=$($response.result_info.cursors.after)"` when constructing the URI. A single-quoted string would send the variable expression literally in most cases.
Your original loop uses `$response` to build `$uri_with_cursor`, but stores the new request in `$response_cursor`. That means the next iteration still reads the old cursor. Either assign the new result back to `$response`, or consistently use `$response_cursor` when constructing the next URI.

That makes sense. The main issue was mixing the initial response with the response from the loop, so I wasn’t advancing from the newest cursor.