# Upload a file

> `201` with the file's address (`file:…`), which any task input takes.

`POST https://api.refabric.com/v1/files`

**Modes**

- **1. By URL** (JSON `{url}`) — a public https address; a URL that already has an address answers that file.
- **2. By bytes** (multipart) — the file itself.

**Authentication.** A key with `files:write`: an upload is stored in your account.

**Key features**

- Accepted types: PNG, JPEG, WebP, GIF, BMP or PDF. The size cap is read live from `GET /v1/meta`.

**Common use cases**

- Give a product photo an address once and pass it to several tasks.
- Attach what you know about the product (`name`, `external_id`, `items`).

**Conflicts.** The same `url` answers the same file; the same `url` with different details answers `409 conflict`. Bytes sent again create a new file.

**See also**

- `GET /v1/files/{ref}`
- `POST /v1/tasks/{name}`

Authentication: `Authorization: Key $REFABRIC_API_KEY`, scope `files:write`.

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

## Body (application/json)

- `url` (string, _required_, min length 1) — A URL of a stored object. The same file sent at different spellings of its URL is one file.
- `name` (string, _optional_, default: ``) — The product's name, shown in listings.
- `external_id` (string | null, _optional_) — Your own id for the product (SKU). A number is taken as text.
- `description` (string, _optional_, default: ``) — A fit note: how the garment fits or should sit.
- `category` (string, _optional_) — What the product is. The shoots read it from the product: how it is worn, framed and restored.
  Values: `top` (Shirts, blouses, T-shirts, knitwear and other upper-body garments. When the product is worn on the upper body.); `bottom` (Trousers, skirts, shorts and other lower-body garments. When the product is worn on the lower body.); `dress` (Dresses and jumpsuits — one piece covering upper and lower body. When the product is one piece covering upper and lower body.); `outerwear` (Coats, jackets and blazers worn over other garments. When the product is worn over other garments.); `full_look` (A complete outfit of several garments worn together. When the photo shows a whole outfit rather than one garment.); `accessory` (Bags, belts, hats, scarves, jewellery and similar items. When the product is an accessory: a bag, belt, hat, scarf or jewellery.); `shoe` (Footwear. When the product is footwear.); `swimwear` (Swimsuits, bikinis and swim shorts. When the product is swimwear.); `lingerie` (Underwear and sleepwear. When the product is underwear or sleepwear.)
- `items` (array<object>, _optional_) — Your other photos of the product: its back/side, its label, its details.
  - `type` (string, _required_) — What the photo is.
    Values: `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.); `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.)
  - `image` (string, _required_, min length 1) — The photo: a url, `file:…` or `art:…`.
  - `view` (string, _optional_, default: ``) — Which side it shows: `back` · `side` for a `product` photo (required), `front` · `back` for a `detail` (optional); a `label` has none.

## Response 201

Created: the body is what was made.

- `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"]`

```json
{
  "url": "https://files.refabric.com/art/3f2a.png",
  "media_type": "image/png",
  "file": "art:3f2a",
  "task": "image.expand",
  "job_id": "9b2f4c1d0e8a",
  "created_at": "2026-10-05T09:30:12Z",
  "data": {}
}
```

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

## Request

```python
import os
import requests

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

payload = { "url": "string" }
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/files';
const options = {
    method: 'POST',
    headers: {Authorization: `Key ${process.env.REFABRIC_API_KEY}`, 'Content-Type': 'application/json'},
    body: '{"url":"string"}'
};

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/files \
    --header "Authorization: Key $REFABRIC_API_KEY" \
    --header 'Content-Type: application/json' \
    --data '{"url":"string"}'
```
