Pagination

All multi-record Vista Direct API endpoints support forward-only paging with a continuation token.

Prefer /cache/search for full extracts

For reading an entire cache object (unfiltered or filtered), use:

POST /direct/subscribers/{subscriber_code}/vista/.../data/{object}/cache/search

Page by sending the previous response’s continuationToken in the next request body.

GET .../cache also supports paging via limit, continuationToken, and a next URL. For large full syncs, prefer POST /cache/search: it uses the Cosmos query path designed for continuation in the JSON body and avoids query-string token handling. If you use GET /cache, follow the next URL from each response rather than rebuilding the query string from a hand-edited token.

When to stop

ResponseAction
continuationToken present (search) or next present (GET)Request the next page
count / page size is 0 but token / next still presentKeep paging — expected with Cosmos
continuationToken null/absent (search) or no next (GET)Done

Do not treat count: 0 alone as end of data.

continuationToken on /cache/search

  • Opaque value from the previous search response.
  • Send it back exactly as received in the JSON body (same JSON shape).
  • It is often a JSON array of objects with token and range (Cosmos internals). Do not construct or edit it.
  • On the first call, omit it (or null/empty).
  • In OpenAPI / Try It, if the field is labeled “string,” still paste the JSON value from the previous response (the [...] array), not a reinvented string. Prefer editing the full request body JSON.

Example subsequent request body:

{
  "continuationToken": [
    {
      "token": "+RID:...#RT:1#...",
      "range": {
        "min": "...",
        "max": "..."
      }
    }
  ]
}

Limits

  • Multi-record responses are capped (typically up to 1,000 records, or about 1 MB for search, whichever applies first).
  • The API may return fewer records than the requested limit — including, on rare occasions, 0 records with a continuation token still present.

Make sure to use the continuation token exactly as provided. Do not inadvertently introduce additional quotation marks or other changes in JSON handling.

Fetch all employees example (PowerShell)

This example pages POST .../vista/pr/2/data/employees/cache/search (Payroll employees cache, unfiltered) until continuationToken is absent. Replace {subscriber_code} with your subscriber code, and set PROD_APP_NETWORK_API_KEY (or hard-code a key only in a secure local test).

# Stop script execution if any command fails (equivalent to set -e)
$ErrorActionPreference = "Stop"

# Object: vista/pr/2/data/employees (Payroll employees cache search)
$ApiUrl = "https://api.xchange.trimble.com/connect/v1/direct/subscribers/{subscriber_code}/vista/pr/2/data/employees/cache/search"
$AppKey = $env:PROD_APP_NETWORK_API_KEY

# Validate environment variable
if ([string]::IsNullOrEmpty($AppKey)) {
    Write-Error "Error: PROD_APP_NETWORK_API_KEY is not set."
    exit 1
}

$TotalRecords = 0
$RequestCount = 0
$ContinuationToken = $null

while ($true) {
    # Build payload object (unfiltered search; filters omitted)
    $PayloadObj = [ordered]@{
        continuationToken = if ([string]::IsNullOrEmpty($ContinuationToken)) { $null } else { $ContinuationToken }
    }
    $Payload = $PayloadObj | ConvertTo-Json -Compress

    # Set up headers
    $Headers = @{
        "Content-Type"      = "application/json"
        "x-application-key" = $AppKey
    }

    try {
        # Send POST request and automatically parse JSON response
        $Response = Invoke-RestMethod -Uri $ApiUrl -Method Post -Headers $Headers -Body $Payload
    } catch {
        Write-Error "Error: Request #$($RequestCount + 1) failed."
        Write-Error $_.Exception.Message
        exit 1
    }

    # Extract fields (fallback to 0 if count is missing)
    $Count = if ($null -ne $Response.count) { [int]$Response.count } else { 0 }
    $LatestToken = $Response.continuationToken

    $TotalRecords += $Count
    $RequestCount += 1

    # Log progress
    $TokenPresent = if (![string]::IsNullOrEmpty($LatestToken)) { "true" } else { "false" }
    Write-Host "Response #${RequestCount}: count=$Count, running_total=$TotalRecords, continuation_token_present=$TokenPresent"

    # Break loop if no more pagination tokens are provided
    if ([string]::IsNullOrEmpty($LatestToken)) {
        break
    }

    $ContinuationToken = $LatestToken
}

Write-Host "Done. Total records returned: $TotalRecords"

What’s Next

Now you know enough to start getting and changing data.