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

# Using query jobs

> Use query jobs to query and export data from Unify.

## Overview

Query jobs let you query and export data asynchronously. Create a job, poll it
until processing finishes, and then retrieve the results one page at a time.

Jobs run in seconds for small queries and minutes for large queries. You can use
them for recurring syncs or one-time exports. For targeted lookups, the normal
endpoints can be faster and offer higher rate limits.

## How it works

The following walkthrough uses sequence enrollments as an example.

<Steps titleSize="h3">
  <Step title="Create a query job">
    Create a job for the data you want to query. This request queries all
    sequence enrollments:

    ```bash theme={null}
    curl -X POST 'https://api.unifygtm.com/sequences/v1/enrollments/query-jobs' \
      -H 'X-Api-Key: ${UNIFY_API_KEY}'
    ```

    The response includes the job ID, current status, and expiration time:

    ```json theme={null}
    {
      "job_id": "<string>",
      "status": "IN_PROGRESS",
      "expires_at": "2026-09-01T12:00:00Z"
    }
    ```
  </Step>

  <Step title="Poll the job">
    Poll the job until it reaches a terminal status:

    ```bash theme={null}
    curl 'https://api.unifygtm.com/sequences/v1/enrollments/query-jobs/<job_id>' \
      -H 'X-Api-Key: ${UNIFY_API_KEY}'
    ```

    A finished job includes the number of result rows:

    ```json theme={null}
    {
      "job_id": "<string>",
      "status": "FINISHED",
      "total_rows": 123,
      "error_code": null,
      "created_at": "2026-08-31T12:00:00Z",
      "expires_at": "2026-09-01T12:00:00Z",
      "canceled_at": null
    }
    ```
  </Step>

  <Step title="Retrieve the results">
    After the job reaches `FINISHED`, retrieve each page of results:

    ```bash theme={null}
    curl 'https://api.unifygtm.com/sequences/v1/enrollments/query-jobs/<job_id>/results?page=1&page_size=1000' \
      -H 'X-Api-Key: ${UNIFY_API_KEY}' \
      -H 'Accept: application/json'
    ```

    ```json theme={null}
    {
      "total": 123,
      "page": 1,
      "page_size": 1000,
      "data": [
        {
          "id": "<string>",
          "updated_at": "2026-08-31T11:58:00Z"
        }
      ]
    }
    ```
  </Step>
</Steps>

## Examples

<CardGroup cols={2}>
  <Card title="Query records" href="/developers/api/data/records/query-records/create" icon="database">
    Export records from an object.
  </Card>

  <Card title="Query enrollments" href="/developers/api/sequences/enrollments/query-enrollments/create" icon="list-check">
    Export sequence enrollments.
  </Card>

  <Card title="Query enrollment steps" href="/developers/api/sequences/enrollments/query-enrollment-steps/create" icon="list-ol">
    Export enrollment steps.
  </Card>

  <Card title="Query tasks" href="/developers/api/tasks/tasks/query-tasks/create" icon="square-check">
    Export tasks.
  </Card>
</CardGroup>

## Usage guide

### Job endpoints

| Method | Path | Description |
| - | - | - |
| `POST` | `{base}/query-jobs` | Create a query job |
| `GET` | `{base}/query-jobs` | List query jobs |
| `GET` | `{base}/query-jobs/{job_id}` | Get a query job |
| `POST` | `{base}/query-jobs/{job_id}/cancel` | Cancel a query job |
| `GET` | `{base}/query-jobs/{job_id}/results` | Retrieve results |

Each resource follows the same job management pattern summarized here. The API
reference pages describe the available filters and results for each resource.

### Job statuses

A query job has one of the following statuses:

| Status | Meaning |
| :- | :- |
| `IN_PROGRESS` | Results are still being prepared. |
| `FINISHED` | The job completed and results are available. |
| `FAILED` | The job failed. Check `error_code` in the job metadata. |
| `CANCELED` | The job was canceled before completion. |
| `EXPIRED` | The job or its results are no longer available. |

Jobs and results are available until `expires_at`, which is 24 hours after job
creation. Retrieve all required pages before that time.

### List and cancel jobs

List query jobs by sending a `GET` request to a resource's `query-jobs` path.
List endpoints accept the following query parameters:

| Parameter | Description |
| :- | :- |
| `limit` | Number of jobs to return. The default and maximum are `100`. |
| `cursor` | Opaque pagination cursor from the previous response. |
| `status` | Optional job status filter. |

Cancel an in-progress job by sending a `POST` request to its `cancel` endpoint:

```bash theme={null}
curl -X POST 'https://api.unifygtm.com/sequences/v1/enrollments/query-jobs/<job_id>/cancel' \
  -H 'X-Api-Key: ${UNIFY_API_KEY}'
```

Only `IN_PROGRESS` jobs can be canceled.

### Retrieve results

Result pagination is page based. Rows use a stable ordering with a tie-breaker,
so pages remain stable for a finished job.

#### JSON

JSON is the default response format:

```http theme={null}
Accept: application/json
```

| Limit | Value |
| :- | :- |
| Default `page_size` | `1000` |
| Maximum `page_size` | `2000` |
| Maximum raw payload size | `8 MiB` |

Request a smaller page or use NDJSON if a JSON page is too large.

#### NDJSON

Use NDJSON to stream larger pages:

```http theme={null}
Accept: application/x-ndjson
```

```bash theme={null}
curl -N 'https://api.unifygtm.com/sequences/v1/enrollments/query-jobs/<job_id>/results?page=1&page_size=10000' \
  -H 'X-Api-Key: ${UNIFY_API_KEY}' \
  -H 'Accept: application/x-ndjson'
```

NDJSON responses return one JSON object per line. Pagination metadata is
returned in response headers:

```http theme={null}
x-total: 123
x-page: 1
x-page-size: 10000
```

The maximum NDJSON `page_size` is `10000`.

### Rate limits

Rate limits are applied by operation type:

| Operation | Rate limit |
| :- | :- |
| Create query jobs | Approximately 100 jobs per day |
| Get or list job status | Approximately 10 requests per second |
| Retrieve or stream results | Approximately 5 requests per second |
| Cancel in-progress jobs | Approximately 1 request per second |

Poll conservatively, page through results with bounded concurrency, and reuse a
finished job instead of creating another snapshot. If you receive `429 Too Many
Requests`, wait before retrying and honor the `Retry-After` header.

### Best practices

* **Request only the data you need.** Use filters and focused field selections
  to keep queries small and fast.
* **Design for retries.** Store the `job_id` and current status.
* **Process results idempotently.** Use stable record IDs so retrying a page does
  not create duplicates.
* **Use NDJSON for large pages.** NDJSON streams results and supports larger
  pages than JSON.
* **Retrieve results before expiration.** Create a new job if its results have
  expired.


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