> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usestatemachines.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Import and query data with Bulk API 2.0

> Upload CSV fixtures, inspect row results, and retrieve paginated query exports.

Use Bulk API 2.0 when your client imports or exports CSV. Connect to the environment with an actor that can access the relevant objects and fields.

The paths below use `{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:

```http theme={null}
POST /services/data/v{version}/jobs/ingest
Content-Type: application/json

{"object":"Account","operation":"insert","contentType":"CSV","lineEnding":"LF","columnDelimiter":"COMMA"}
```

Save the returned job ID. The new ingest job is `Open`.

Upload CSV to the job's batches resource:

```http theme={null}
PUT /services/data/v{version}/jobs/ingest/{jobId}/batches
Content-Type: text/csv

Name,Description
Juniper Sample Company,First test account
Willow Sample Company,Second test account
```

Finish the upload by changing the state:

```http theme={null}
PATCH /services/data/v{version}/jobs/ingest/{jobId}
Content-Type: application/json

{"state":"UploadComplete"}
```

Read `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's `numberRecordsProcessed` and `numberRecordsFailed`. Fetch the result resources under the ingest job:

* `/successfulResults` contains successful rows and their Salesforce IDs.
* `/failedResults` contains rejected rows and their errors.
* `/unprocessedrecords` contains rows that were not processed.

A completed job can contain row failures. Assert the row outcomes your test expects, then query or retrieve the stored records. A successful CSV upload only confirms receipt of the file.

For updates or deletes, include record IDs in the CSV. For upserts, set `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:

```http theme={null}
POST /services/data/v{version}/jobs/query
Content-Type: application/json

{"operation":"query","query":"SELECT Id, Name FROM Account ORDER BY Id","contentType":"CSV"}
```

Use `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](/apps/salesforce-query) 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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.