# Export orders for a date range with a bulk operation

> Export every Shopify order in a date range, with line items, to a JSONL file using bulkOperationRunQuery and an orders search filter.

Page: https://lintelagency.com/resources/graphql/bulk-export-orders-by-date

## In short

To export Shopify orders for a date range, pass an orders query with a created_at filter to the bulkOperationRunQuery mutation, poll the bulkOperation query until the status is COMPLETED, then download the JSONL file from url. Line items arrive as separate lines with a __parentId. Your app needs read_orders, plus read_all_orders for orders older than 60 days.

## Facts

- **API:** Admin GraphQL API
- **Operations:** bulkOperationRunQuery, bulkOperation
- **Access scopes:** read_orders; add read_all_orders for orders older than 60 days
- **Replaces (REST):** GET /admin/api/orders.json with created_at_min and created_at_max
- **API version:** 2026-10
- **Last checked:** 2 November 2026

## How to use it

1. Write the orders query with a search filter such as created_at:>=2026-07-01 AND created_at:<2026-10-01. Put only the fields you need inside it.
2. Send it as the query variable of StartOrderExport and keep the returned bulk operation ID.
3. Poll OrderExportStatus every few seconds, or subscribe to the bulk_operations/finish webhook, until status is COMPLETED.
4. Download the file at url and read it line by line. Attach each line item to its order with __parentId.

## Code

### bulk-operation-run-query.graphql

```graphql
mutation StartOrderExport($query: String!) {
  bulkOperationRunQuery(query: $query) {
    bulkOperation {
      id
      status
    }
    userErrors {
      field
      message
    }
  }
}
```

### bulk-operation-run-query.variables.json

```json
{
  "query": "{ orders(query: \"created_at:>=2026-07-01 AND created_at:<2026-10-01\", sortKey: CREATED_AT) { edges { node { id name createdAt displayFinancialStatus displayFulfillmentStatus currencyCode totalPriceSet { shopMoney { amount currencyCode } } lineItems { edges { node { id sku quantity originalUnitPriceSet { shopMoney { amount } } } } } } } } }"
}
```

### bulk-operation-run-query.response.json

```json
{
  "data": {
    "bulkOperationRunQuery": {
      "bulkOperation": {
        "id": "gid://shopify/BulkOperation/1234567890",
        "status": "CREATED"
      },
      "userErrors": []
    }
  }
}
```

### bulk-operation-status.graphql

```graphql
query OrderExportStatus($id: ID!) {
  bulkOperation(id: $id) {
    id
    status
    errorCode
    objectCount
    rootObjectCount
    url
    partialDataUrl
  }
}
```

### bulk-operation-status.variables.json

```json
{
  "id": "gid://shopify/BulkOperation/1234567890"
}
```

### bulk-operation-status.response.json

```json
{
  "data": {
    "bulkOperation": {
      "id": "gid://shopify/BulkOperation/1234567890",
      "status": "COMPLETED",
      "errorCode": null,
      "objectCount": "15872",
      "rootObjectCount": "4210",
      "url": "https://storage.googleapis.com/shopify-tiers-assets-prod-us-east1/bulk-operation-outputs/example.jsonl",
      "partialDataUrl": null
    }
  }
}
```

### result.jsonl

```text
{"id":"gid://shopify/Order/1111111111","name":"#1001","createdAt":"2026-07-01T08:14:22Z","displayFinancialStatus":"PAID","displayFulfillmentStatus":"FULFILLED","currencyCode":"EUR","totalPriceSet":{"shopMoney":{"amount":"98.00","currencyCode":"EUR"}}}
{"id":"gid://shopify/LineItem/2222222222","sku":"LS-M","quantity":2,"originalUnitPriceSet":{"shopMoney":{"amount":"49.00"}},"__parentId":"gid://shopify/Order/1111111111"}
```

## Limits and edge cases

- Without read_all_orders, only orders created in the last 60 days are returned. Public apps need Shopify’s approval for it; apps created in the Dev Dashboard for stores in your own organization don’t.
- The filter takes a date or a full ISO 8601 timestamp, such as created_at:>='2026-07-01T00:00:00Z', when the range must be exact to the second.
- Customer fields such as email and addresses fall under Shopify’s protected customer data rules. Request that access before adding them to the query.
- rootObjectCount counts orders only; objectCount also counts the line items.

## Questions

### How do I export Shopify orders by date with GraphQL?

Run bulkOperationRunQuery with an orders connection filtered by created_at, wait for the operation to complete, then download the JSONL file. For a few hundred orders, a paginated orders query with the same filter is enough.

### Why does my export stop at 60 days?

read_orders only covers orders created in the last 60 days. Request read_all_orders alongside it to read older orders.

### Can I filter by updated date instead of created date?

Yes. The orders query accepts updated_at and processed_at filters too, which suits incremental syncs that only pick up changed orders.

### How do I turn the JSONL into a CSV?

Read the file line by line, keep orders in a map by id, add each line item to its parent with __parentId, then write one CSV row per order or per line item.

## Shopify documentation

- [Perform bulk operations with the GraphQL Admin API](https://shopify.dev/docs/api/usage/bulk-operations/queries)
- [orders query and search filters](https://shopify.dev/docs/api/admin-graphql/latest/queries/orders)
- [Access scopes: orders permissions](https://shopify.dev/docs/api/usage/access-scopes)

## Related

- [Export all products with a bulk operation](https://lintelagency.com/resources/graphql/bulk-export-products)
- [Keeping inventory in sync with another system](https://lintelagency.com/journal/sync-inventory-external-system)
- [Migrating to Shopify: what breaks and how to plan for it](https://lintelagency.com/journal/migrating-to-shopify-what-breaks)

License: MIT. Free to use in your own store and in client work.
