POST to /services/data/vXX.0/jobs/query with operation set to query and a SOQL string that may include parent relationship dot fields
Poll the job status endpoint until the state is JobComplete
Fetch the results CSV via GET /services/data/vXX.0/jobs/query/<jobId>/results with a Sforce-Locator header starting empty
Each response includes a Sforce-NumberOfRecords header and a Sforce-Locator header; if Sforce-Locator is non-null, repeat the GET passing that locator to retrieve the next chunk
Continue until the response Sforce-Locator header is null, indicating all records have been downloaded
Parse each CSV chunk incrementally to avoid loading the entire result set into memory
Known gotchas
Bulk API 2.0 query uses a locator-based pagination scheme that differs from Bulk API 1.0's result batches; the two APIs are not interchangeable
Including too many relationship traversal fields in the SOQL can cause the job to fail; simplify the query and join data post-download if needed
The CSV header row is only included in the first chunk; subsequent locator-fetched chunks contain data rows only
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp