# List jobs

> Page through your parent search jobs, newest first, with cursor pagination and optional state / surface filters.

`GET /v1/jobs` returns your **parent** jobs, newest first, with cursor pagination. Reads are owner-scoped: a restricted `sk_*` key sees only its own jobs.

<Note>
  This endpoint lists **parents** only. To read a single parent's rollup or one
  child's [Envelope](/guides/output-formats), use [`GET
  /v1/jobs/:id`](/api-reference/get-job).
</Note>

## Query parameters

<ParamField query="limit" type="integer" default="20">
  Page size, `1`–`100`.
</ParamField>

<ParamField query="state" type="string">
  Filter by parent lifecycle state: `queued`, `processing`, `completed`,
  `partial`, `failed`, `canceled`, or `expired`.
</ParamField>

<ParamField query="surface" type="string">
  Filter to parents that include a child on this surface (e.g. `chatgpt`).
</ParamField>

<ParamField query="cursor" type="string">
  Opaque cursor from a previous page's `nextCursor`. Omit for the first page.
</ParamField>

## Request

<CodeGroup>

```bash cURL
curl "https://api.aisearchapi.dev/v1/jobs?limit=20&state=completed" \
  -H "Authorization: Bearer $AISEARCH_API_KEY"
```

```javascript Node
const res = await fetch(
  'https://api.aisearchapi.dev/v1/jobs?limit=20&state=completed',
  { headers: { Authorization: `Bearer ${process.env.AISEARCH_API_KEY}` } },
);
const page = await res.json();
```

```python Python
import os, requests

res = requests.get(
    "https://api.aisearchapi.dev/v1/jobs",
    params={"limit": 20, "state": "completed"},
    headers={"Authorization": f"Bearer {os.environ['AISEARCH_API_KEY']}"},
)
page = res.json()
```

</CodeGroup>

## Response

```json 200 OK
{
  "items": [
    {
      "id": "job_8t2q",
      "status": "completed",
      "prompt": "best crm for startups",
      "createdAt": "2026-06-30T17:02:11Z"
    },
    {
      "id": "job_5k9d",
      "status": "partial",
      "prompt": "cheapest ev in europe 2026",
      "createdAt": "2026-06-30T16:41:02Z"
    }
  ],
  "nextCursor": "eyJvZmZzZXQiOjIwfQ"
}
```

<ResponseField name="items" type="object[]">
  One entry per parent job, newest first.

  <Expandable title="item">
    <ResponseField name="id" type="string">
      The parent job id (dotless). Read it with [`GET
      /v1/jobs/:id`](/api-reference/get-job) for its rollup and children.
    </ResponseField>
    <ResponseField name="status" type="string">
      The parent rollup state.
    </ResponseField>
    <ResponseField name="prompt" type="string">
      The submitted query.
    </ResponseField>
    <ResponseField name="createdAt" type="string">
      ISO-8601 submission timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="nextCursor" type="string | null">
  Pass as `?cursor=` to fetch the next page. `null` on the last page.
</ResponseField>

## Paginate to the end

<CodeGroup>

```javascript Node
async function* allJobs() {
  let cursor;
  do {
    const url = new URL('https://api.aisearchapi.dev/v1/jobs');
    url.searchParams.set('limit', '100');
    if (cursor) url.searchParams.set('cursor', cursor);
    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.AISEARCH_API_KEY}` },
    });
    const page = await res.json();
    yield* page.items;
    cursor = page.nextCursor;
  } while (cursor);
}

for await (const job of allJobs()) console.log(job.id, job.status);
```

```python Python
import os, requests

def all_jobs():
    cursor = None
    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor
        res = requests.get(
            "https://api.aisearchapi.dev/v1/jobs",
            params=params,
            headers={"Authorization": f"Bearer {os.environ['AISEARCH_API_KEY']}"},
        )
        page = res.json()
        yield from page["items"]
        cursor = page["nextCursor"]
        if not cursor:
            break

for job in all_jobs():
    print(job["id"], job["status"])
```

</CodeGroup>

<CardGroup cols={2}>
  <Card title="Get a job" icon="file-lines" href="/api-reference/get-job">
    Read a parent rollup or a single child Envelope.
  </Card>
  <Card title="Cancel a job" icon="ban" href="/api-reference/cancel-job">
    Stop a parent's remaining children.
  </Card>
</CardGroup>
