{version} for a supported Bulk API version and {jobId} for the ID returned at job creation. Send requests through your authenticated client at the app URL. Keep the same actor and API version throughout each job.
Create an ingest job
Discover the target object’s fields before preparing the CSV. For a fictitious account fixture, create an insert job:Open.
Upload CSV to the job’s batches resource:
GET /services/data/v{version}/jobs/ingest/{jobId} until the job reaches a terminal state, such as JobComplete, Failed, or Aborted. Keep completion polling in your integration even if a small replica job finishes before your first status request.
Check each row’s result
Read the job’snumberRecordsProcessed and numberRecordsFailed. Fetch the result resources under the ingest job:
/successfulResultscontains successful rows and their Salesforce IDs./failedResultscontains rejected rows and their errors./unprocessedrecordscontains rows that were not processed.
operation to upsert and provide externalIdFieldName when creating the job. Use a field that describe marks externalId or idLookup. Any other field fails job creation with INVALIDJOB. The replica also implements hardDelete. Use it only when permanent removal is part of your test.
Export a query as CSV
Create a query job with an explicit field list:queryAll as the operation when the export must include deleted records. Save the returned job ID and read its status at /jobs/query/{jobId} under the same version.
After JobComplete, request /jobs/query/{jobId}/results. Parse the CSV by its header names. If the Sforce-Locator response header contains a continuation value rather than null, request the same results endpoint with that value in the locator query parameter. Repeat until the header is null.
Set maxRecords on every results request. The replica’s default page is 50,000 rows, and State Machines refuses an app response larger than 4 MiB with response_too_large. Keep the job’s API version when retrieving pages. Below API version 50.0 the CSV columns are in alphabetical order. From 50.0 they follow the SELECT order. A results request at a version on the other side of that boundary returns CONFLICT.
From API version 58.0, GET /jobs/query/{jobId}/resultPages lists the result pages.
Adjust a query for Bulk
Bulk query jobs reject grouping, aggregate functions,OFFSET, TYPEOF, and parent-to-child subqueries. They also reject compound address and location fields. Select supported scalar component fields instead.
Prefer explicit field names. FIELDS(ALL) and FIELDS(CUSTOM) are unsupported. FIELDS(STANDARD) expands the actor-visible standard fields, but the expanded selection still fails if it includes a compound field.
Use REST queries when your test needs a supported query form that Bulk does not accept. Keep Bulk-specific failure assertions for clients that must report an invalid job correctly.