# Run a task

> `202` with the new job's `job_id` and its status, result and cancel URLs — or, while waiting, the job's result itself.

`POST https://api.refabric.com/v1/tasks/{name}`

**Modes**

- **1. Asynchronous** (the default) — answers `202` at once; follow the job at its status URL, or name a `webhook_url` to be called when it ends.
- **2. Wait** (`Prefer: wait=N`) — holds the answer up to N seconds and answers the result when the job ends in time; otherwise `202`, as when asynchronous.

**Authentication.** A key with `tasks:run`: a job spends your credits.

**Key features**

- `Prefer: wait` waits 60 seconds at most.
- `X-Refabric-Start-Timeout` takes 0.1 seconds to 24 hours: a job that has not started by then ends without starting.
- A webhook is tried up to 31 times.
- A body field the task's input schema (`GET /v1/tasks/{name}`) does not list is refused (`422 field_not_accepted`, naming it), never ignored.

**Common use cases**

- Start a job from your server and poll it or wait for its webhook.
- Run a short job and take its result in the same call with `Prefer: wait`.

**Conflicts.** An `Idempotency-Key` sent again with another body answers `409 idempotency_key_reused`; sent again while the first request runs, `409 request_in_progress`.

**See also**

- `POST /v1/tasks/{name}/estimate`
- `GET /v1/jobs/{job_id}`
- `GET /v1/tasks/{name}`

Authentication: `Authorization: Key $REFABRIC_API_KEY`, scope `tasks:run`.

## Path parameters

- `name` (string, _required_)

## Query parameters

- `webhook_url` (string, _optional_, default: ``) — An https endpoint of yours to POST the result to. Signed with ED25519 — verify it with `/.well-known/jwks.json`. Tried up to 31 times; a 3xx or 4xx is final.

## 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.
- `Idempotency-Key` (string, _optional_) — Makes a retry safe: the same key with the same request answers the first answer again; with a different request it is refused.
- `Prefer` (string, _optional_) — wait=N: hold the answer up to N seconds for the job to end (60 at most).
- `X-Refabric-Start-Timeout` (number, _optional_) — Seconds the job may wait to start, from 0.1 to 86400; past it, it ends without running.

## Response 200

Done: the answer is in the body.

- `job_id` (string, _required_) — The job.
  Example: `9b2f4c1d0e8a`
- `files` (array<object>, _required_) — The files, in the order the job delivered them.
  - `url` (string, _required_) — Where the file is. A public, permanent address you can open or download.
    Example: `https://files.refabric.com/art/3f2a.png`
  - `media_type` (string, _required_) — The file's standard media type.
    Example: `image/png`
  - `file` (string, _required_) — Its address; pass it to a task as it is.
    Example: `art:3f2a`
  - `task` (string | null, _optional_) — The task that made it.
    Example: `image.expand`
  - `job_id` (string | null, _optional_) — The job that made it.
    Example: `9b2f4c1d0e8a`
  - `created_at` (string | null, _optional_) — When it was made, ISO-8601 in UTC.
    Example: `2026-10-05T09:30:12Z`
  - `data` (object | null, _optional_) — What the file means, in the record vocabulary.
    - `name` (string | null, _optional_) — The record's name.
      Example: `SS27`
    - `description` (string | null, _optional_) — What the record is, in words.
      Example: `A calm palette.`
    - `status` (string | null, _optional_) — Whether it can be used yet.
      Values: `processing` (Still being made or analysed. Read it again later.); `ready` (Finished. It can be passed to a task.); `failed` (It could not be made. Its content is missing.)
      Example: `ready`
    - `colours` (array<object> | null, _optional_) — Its colours.
      Example: `[{"hex":"#1f2a44"}]`
      - `hex` (string, _required_) — The colour as `#rrggbb`.
        Example: `#1f2a44`
      - `name` (string | null, _optional_) — Its name, when known.
        Example: `Navy`
      - `pantone` (string | null, _optional_) — The nearest Pantone code, when known.
        Example: `19-4024 TCX`
    - `items` (array<object> | null, _optional_) — Its parts (a pose preset: its poses and views).
      Example: `[{"type":"fabric"}]`
      - ItemEntry
        - `type` (string, _required_) — What the part is.
          Values: `fabric` (A fabric: its swatch or a photo of it. When the image is a fabric swatch or a photo of a fabric.); `print` (A print or pattern. When the image is a print or pattern.); `look` (A garment or outfit, as a photo or a design. When the image is a garment or an outfit.); `detail` (A close crop of one detail of a look or a product (a collar, a pocket). When the image is a close crop of one detail.); `design` (One cell of a range plan: a design made for one garment line.); `other` (Any other image the record holds. When the image is none of the other kinds.); `product` (A photo of the product itself, as supplied (`view`: which side). When the photo is the product itself; `view` says which side.); `label` (A photo of the product's label (care, size or brand label). When the photo is of the product's label.); `ghost` (The product on an invisible (ghost) mannequin (`view`: which side). When you want the product shown on an invisible mannequin.); `flat` (The product laid flat, as a flat-lay photo (`view`: which side). When you want the product laid flat.); `close_up` (A close-up of the product's fabric and finish (one per product in a shoot). Not `detail`, which is a crop of one trim or component of a look. When you want a close-up of the product's fabric and finish.)
          Example: `fabric`
        - `view` (string | null, _optional_) — Which side it shows.
          Example: `front`
        - `name` (string | null, _optional_) — Its name.
          Example: `Wool twill`
        - `external_id` (string | null, _optional_) — Your own id for it, when you sent one.
          Example: `SKU-1`
        - `description` (string | null, _optional_) — What it is, in words.
          Example: `A navy wool twill.`
        - `url` (string | null, _optional_) — Its image — pass it to a task as it is.
          Example: `https://files.refabric.com/art/3f2a.png`
        - `status` (string | null, _optional_) — Whether it can be used yet.
          Values: `processing` (Still being made or analysed. Read it again later.); `ready` (Finished. It can be passed to a task.); `failed` (It could not be made. Its content is missing.)
          Example: `ready`
      - PresetItem
        - `kind` (string, _required_) — How the entry names what it wants: a saved pose, an image, words, or a product view.
          Example: `view`
        - `ref` (string, _required_) — The pose's address (`pose:…`); empty for a view.
          Example: `pose:812`
        - `angle` (string | null, _required_) — The pose's camera angle.
          Example: `front`
        - `view` (string | null, _required_) — The product view it shows.
          Example: `back`
    - `keywords` (array<string> | null, _optional_) — Words that sum it up.
      Example: `["tailoring"]`
- `has_more` (boolean, _required_) — More files are on the next page.
  Example: `false`
- `next_cursor` (string | null, _optional_) — Present when `has_more`: send it as `cursor` to the result read for the rest.
- `summary` (object | null, _optional_) — Present when the task has words to count.
  - `requested` (integer | null, _optional_) — Outputs asked for.
    Example: `3`
  - `delivered` (integer | null, _optional_) — Outputs made.
    Example: `2`
  - `warnings` (array<object> | null, _optional_) — Notes on what was not made.
    - `code` (string, _required_) — The warning's catalogue code.
      Example: `output_not_produced`
    - `message` (string, _required_) — What happened, in words.
      Example: `This pose was not made.`
    - `field` (string | null, _optional_) — The request field it is about.
      Example: `poses.items[1]`

```json
{
  "job_id": "9b2f4c1d0e8a",
  "files": [],
  "has_more": false,
  "next_cursor": null,
  "summary": {}
}
```

## Response 202

Accepted: the work goes on after this answer; the body says where to follow it.

- `job_id` (string, _required_) — The job you started.
  Example: `9b2f4c1d0e8a`
- `lifecycle` (string, _required_) — Where the job is now.
  Values: `queued` (Accepted and waiting to start.); `running` (Being made.); `terminal` (Ended. `outcome` says how.)
  Example: `queued`
- `status_url` (string, _required_) — Read the job here (`GET`), as often as you like.
  Example: `http://v3-api.refabric.com/v1/jobs/9b2f4c1d0e8a`
- `result_url` (string, _required_) — Read its result here (`GET`) once it has succeeded.
  Example: `http://v3-api.refabric.com/v1/jobs/9b2f4c1d0e8a/result`
- `cancel_url` (string, _required_) — Ask for it to stop here (`PUT`).
  Example: `http://v3-api.refabric.com/v1/jobs/9b2f4c1d0e8a/cancel`

```json
{
  "job_id": "9b2f4c1d0e8a",
  "lifecycle": "queued",
  "status_url": "http://v3-api.refabric.com/v1/jobs/9b2f4c1d0e8a",
  "result_url": "http://v3-api.refabric.com/v1/jobs/9b2f4c1d0e8a/result",
  "cancel_url": "http://v3-api.refabric.com/v1/jobs/9b2f4c1d0e8a/cancel"
}
```

## 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 402

Your balance does not cover this request.

```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 404

Nothing has this address.

```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 409

The request conflicts with the current state of what it names.

```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 410

This was removed.

```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 413

The body is larger than this operation takes.

```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 415

The body's media type is not one this operation takes.

```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
  }
}
```

## Response 503

The service cannot take this now; retry after a moment.

```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/tasks/{name}"

payload = {}
headers = {
    "Authorization": f"Key {os.environ['REFABRIC_API_KEY']}",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.refabric.com/v1/tasks/{name}';
const options = {
    method: 'POST',
    headers: {Authorization: `Key ${process.env.REFABRIC_API_KEY}`, 'Content-Type': 'application/json'},
    body: '{}'
};

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

```bash
curl --request POST \
    --url https://api.refabric.com/v1/tasks/{name} \
    --header "Authorization: Key $REFABRIC_API_KEY" \
    --header 'Content-Type: application/json' \
    --data '{}'
```
