# List jobs

> Your jobs, newest first — every job of the account, whichever key or the app started it; each row names the key that started it.

`GET https://api.refabric.com/v1/jobs`

**Filters and sorting**

- `outcome` takes several values, repeated (`?outcome=failed&outcome=cancelled`) or comma-separated; a job that has not ended has no outcome.
- `start` / `end` narrow by the time a job was queued, `[start, end)`; without either, every job is listed.

**Authentication.** A key with `jobs:read`: a job and its files are your account's.

**Key features**

- Pages of 50 jobs by default, 200 at most; newest first.
- At most 50 values per filter; a window of 90 days at most.

**Common use cases**

- Find the jobs that failed yesterday.
- List the jobs one key started.

**See also**

- `GET /v1/jobs/{job_id}`
- `GET /v1/account/usage`

Authentication: `Authorization: Key $REFABRIC_API_KEY`, scope `jobs:read`.

## Query parameters

- `limit` (integer, _optional_, default: `50`, 1 to 200) — Items per page: default 50, at most 200.
- `cursor` (string | null, _optional_) — The previous page's `next_cursor`, copied back as it came, for the next page. Never build one.
- `start` (string | null, _optional_, format: date-time) — Inclusive, ISO-8601 (`2026-09-01T00:00:00Z`; no zone means UTC). Default: 30 days before `end`. The window is at most 90 days.
- `end` (string | null, _optional_, format: date-time) — Exclusive, ISO-8601 (no zone means UTC). Default: now.
- `api_key_id` (string | null, _optional_) — Only jobs started with this key of yours (`key_…`, its public id).
- `task` (string | null, _optional_) — Only jobs of this task (`image.generate`).
- `lifecycle` (string, _optional_) — Only jobs at this lifecycle.
  Values: `queued` (Accepted and waiting to start.); `running` (Being made.); `terminal` (Ended. `outcome` says how.)
- `outcome` (array<string> | null, _optional_) — Only jobs with one of these outcomes: succeeded, failed or cancelled; several values are any of them. A job that has not ended has no outcome.

## Header parameters

- `Refabric-Version` (string, _optional_, format: date) — The contract version you wrote against (a date). Absent: the current version.
- `X-Request-ID` (string, _optional_, max length 128) — Your own id for this request; we answer it back under X-Client-Request-ID.

## Response 200

Done: the answer is in the body.

- `items` (array<object>, _required_) — This page's items, in the listing's order.
  - `job_id` (string, _required_) — The job.
    Example: `9b2f4c1d0e8a`
  - `task` (string, _required_) — The task the job runs.
    Example: `image.expand`
  - `lifecycle` (string, _required_) — Where the job is.
    Values: `queued` (Accepted and waiting to start.); `running` (Being made.); `terminal` (Ended. `outcome` says how.)
    Example: `terminal`
  - `outcome` (string | null, _required_) — How the job ended — `null` until its `lifecycle` is `terminal`.
    Values: `succeeded` (It finished; its files are ready.); `failed` (It ended without its result; `error` says why.); `cancelled` (You cancelled it.)
    Example: `succeeded`
  - `queued_at` (string | null, _required_) — When it was accepted, ISO-8601 in UTC.
    Example: `2026-10-05T09:30:00Z`
  - `api_key_id` (string | null, _required_) — The key that started it; `null` for work started in the Refabric app.
    Example: `key_8f3a`
- `has_more` (boolean, _required_) — Whether another page follows this one.
  Example: `false`
- `next_cursor` (string | null, _optional_) — Send it back as `cursor` for the next page. Absent on the last page. Opaque: never build or edit one.
  Example: `eyJsIjoiY2hhbmdlbG9nIn0`

```json
{
  "items": [],
  "next_cursor": "eyJsIjoiY2hhbmdlbG9nIn0",
  "has_more": false
}
```

## Response 400

The request cannot be read as it was sent (a header, the URL or the body's form).

```json
{
  "error": {
    "code": "string",
    "type": "invalid_request",
    "message": "string",
    "field": "string",
    "retryable": true,
    "docs": "string",
    "request_id": "string",
    "ctx": {
      "required": 0,
      "balance": 0,
      "retry_after": 0
    },
    "input": null,
    "job_id": "string",
    "required": 0,
    "balance": 0
  }
}
```

## Response 401

No valid API key was sent.

```json
{
  "error": {
    "code": "string",
    "type": "invalid_request",
    "message": "string",
    "field": "string",
    "retryable": true,
    "docs": "string",
    "request_id": "string",
    "ctx": {
      "required": 0,
      "balance": 0,
      "retry_after": 0
    },
    "input": null,
    "job_id": "string",
    "required": 0,
    "balance": 0
  }
}
```

## Response 403

Your key or your plan does not allow this.

```json
{
  "error": {
    "code": "string",
    "type": "invalid_request",
    "message": "string",
    "field": "string",
    "retryable": true,
    "docs": "string",
    "request_id": "string",
    "ctx": {
      "required": 0,
      "balance": 0,
      "retry_after": 0
    },
    "input": null,
    "job_id": "string",
    "required": 0,
    "balance": 0
  }
}
```

## Response 422

A field is missing or has a value this operation cannot use.

```json
{
  "error": {
    "code": "string",
    "type": "invalid_request",
    "message": "string",
    "field": "string",
    "retryable": true,
    "docs": "string",
    "request_id": "string",
    "ctx": {
      "required": 0,
      "balance": 0,
      "retry_after": 0
    },
    "input": null,
    "job_id": "string",
    "required": 0,
    "balance": 0
  }
}
```

## Response 429

Too many requests: wait for the number of seconds in the Retry-After header.

```json
{
  "error": {
    "code": "string",
    "type": "invalid_request",
    "message": "string",
    "field": "string",
    "retryable": true,
    "docs": "string",
    "request_id": "string",
    "ctx": {
      "required": 0,
      "balance": 0,
      "retry_after": 0
    },
    "input": null,
    "job_id": "string",
    "required": 0,
    "balance": 0
  }
}
```

## Response 500

Something went wrong on our side; retry, and quote the request id if it keeps happening.

```json
{
  "error": {
    "code": "string",
    "type": "invalid_request",
    "message": "string",
    "field": "string",
    "retryable": true,
    "docs": "string",
    "request_id": "string",
    "ctx": {
      "required": 0,
      "balance": 0,
      "retry_after": 0
    },
    "input": null,
    "job_id": "string",
    "required": 0,
    "balance": 0
  }
}
```

## Request

```python
import os
import requests

url = "https://api.refabric.com/v1/jobs"

headers = {"Authorization": f"Key {os.environ['REFABRIC_API_KEY']}"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.refabric.com/v1/jobs';
const options = {method: 'GET', headers: {Authorization: `Key ${process.env.REFABRIC_API_KEY}`}};

try {
    const response = await fetch(url, options);
    const data = await response.json();
    console.log(data);
} catch (error) {
    console.error(error);
}
```

```bash
curl --request GET \
    --url https://api.refabric.com/v1/jobs \
    --header "Authorization: Key $REFABRIC_API_KEY"
```
