# Create a range plan

> Plan a collection from your moodboards: isolate garments from runway looks, or design new pieces line by line. The plan is delivered as one record whose items are its images.

**Endpoint:** `POST https://api.refabric.com/v1/tasks/range_plan.create` · **Task:** `range_plan.create` · **Scope:** `tasks:run` · **Category:** Records & libraries

Name your moodboards and get a collection plan back as one record. With `runway_looks`, each look you pick becomes a flat image of the garment you name. With `new_designs`, each garment line is designed piece by piece from the moodboards, your brand kit and your references. You get a mail when the plan is ready.

## Quick start

```python
import os
import time
import requests

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

job = requests.post(
    "https://api.refabric.com/v1/tasks/range_plan.create",
    headers=headers,
    json={
        "kind": "new_designs",
        "gender": "womenswear",
        "moodboards": [
            "moodboard:5b3d2c1a-7e6f-4a8b-9c0d-1e2f3a4b5c6d",
        ],
        "garments": [
            {
                "garment_type": "jackets",
            },
        ],
    },
).json()
print(job["job_id"])

while True:
    status = requests.get(job["status_url"], headers=headers).json()
    if status["lifecycle"] == "terminal":
        break
    time.sleep(5)

print(requests.get(job["result_url"], headers=headers).json())
```

```javascript
const headers = {
  Authorization: `Key ${process.env.REFABRIC_API_KEY}`,
  "Content-Type": "application/json",
};

const job = await fetch("https://api.refabric.com/v1/tasks/range_plan.create", {
  method: "POST",
  headers,
  body: JSON.stringify({
    "kind": "new_designs",
    "gender": "womenswear",
    "moodboards": [
      "moodboard:5b3d2c1a-7e6f-4a8b-9c0d-1e2f3a4b5c6d"
    ],
    "garments": [
      {
        "garment_type": "jackets"
      }
    ]
  }),
}).then((r) => r.json());
console.log(job.job_id);

let status = job;
while (status.lifecycle !== "terminal") {
  await new Promise((r) => setTimeout(r, 5000));
  status = await fetch(job.status_url, { headers }).then((r) => r.json());
}

console.log(await fetch(job.result_url, { headers }).then((r) => r.json()));
```

```bash
curl -X POST "https://api.refabric.com/v1/tasks/range_plan.create" \
  -H "Authorization: Key $REFABRIC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: wait=60" \
  -d '{"kind":"new_designs","gender":"womenswear","moodboards":["moodboard:5b3d2c1a-7e6f-4a8b-9c0d-1e2f3a4b5c6d"],"garments":[{"garment_type":"jackets"}]}'
```

## Input schema

- `gender` (string, _required_) — Who the collection is for. Required for both kinds.
  Values: `womenswear` (A womenswear collection. For a womenswear collection.); `menswear` (A menswear collection. For a menswear collection.); `unisex` (A collection for everyone: no gender scope. For a collection with no gender scope.)
  Example: `womenswear`
- `moodboards` (array<string>, _required_, at least 1 items) — The moodboards the plan is made from, as ["moodboard:<id>", …] — yours (`GET /v1/refs/moodboard`) or curated ones (`GET /v1/refs/moodboard?curated=true`), at least one, each finished with its analysis. With `runway_looks` the looks come from them; with `new_designs` the collection follows them.
  Example: `["moodboard:5b3d2c1a-7e6f-4a8b-9c0d-1e2f3a4b5c6d"]`
- `kind` (string, _required_) — Which kind of range plan to make. Each kind takes its own fields; the schema shows them per kind.
  Values: `runway_looks` (Isolate garments from real runway looks: pick looks from your moodboards in `looks` and name the garment to take from each. Every look becomes one flat garment image. When your moodboards hold runway looks and you want their garments as flat images.); `new_designs` (Design new pieces as one collection: list the garment lines in `garments`, each with how many images to make. The collection follows the moodboards (and an optional brand kit). When you want new pieces designed as one collection.)
  Example: `new_designs`
- `name` (string, _optional_, default: ``) — The plan's name, shown on the plan and in the ready mail. Optional.
  Example: `SS27 capsule`
- `resolution` (string, _optional_, default: `2K`) — The size of every image of the plan. `2K` is sharp enough for screens and review; ask for `4K` when the result will be printed or zoomed into.
  Values: `2K` (Standard size, for screens and review.); `4K` (Large size, for print and zoom. When the image will be printed or zoomed into.)
  Example: `2K`
- `brand_kit` (string, _optional_, pattern: ^brand_kit:[0-9]+$) — A brand kit whose fabrics, prints, colours and looks the collection is designed with, as "brand_kit:<id>" (`GET /v1/refs/brand_kit`).
  Example: `brand_kit:28`
- `brands` (array<string>, _optional_) — A reference house the collection follows. Its values may change; read them live at `GET /v1/vocab/brand_house`.
  Example: `["Jacquemus"]`
- `looks` (array<object>, _optional_, at least 1 items) — At least one: the runway looks to isolate, each {image, prompt}. Every look becomes one flat image of the garment its prompt names.
  - `image` (string, _required_, pattern: ^(https://|art:|file:).+$) — The url of a look of one of the named moodboards — a `data.items[].url` of `GET /v1/files/moodboard:<id>`. A url of no named moodboard is refused.
  - `prompt` (string, _required_) — Which garment to take from the look, in your words ("the trench coat"). The plan's cell for this look is named by it.
- `garments` (array<object>, _optional_, at least 1 items) — At least one: the garment lines to design, each {garment_type, image_count, prompt, references}. A row's `references` are at most 1 fabric (`use_case: "fabric"`) and 3 details (no `use_case`).
  Example: `[{"garment_type":"jackets","image_count":4,"prompt":"boxy, cropped, raw hems","references":[{"image":"https://files.example.com/range_plan.create/1.jpg","use_case":"fabric"},{"image":"art:c10d55"}]},{"garment_type":"linen wrap skirt","image_count":2}]`
  - `garment_type` (string, _required_) — The garment line; free text is accepted too and used as written. It names the row's cells in the plan.
    Example: `jackets`
  - `image_count` (integer, _optional_, default: `1`, 1 to 20) — How many pieces of this line to design.
    Example: `4`
  - `prompt` (string, _optional_) — The style of this line, in your words ("boxy, cropped").
    Example: `boxy, cropped, raw hems`
  - `references` (array<object>, _optional_, at most 4 items) — Images this line is designed from: its fabric (`use_case: "fabric"`) and details such as a trim or a collar (no `use_case`).
    Example: `[{"image":"https://files.example.com/range_plan.create/1.jpg","use_case":"fabric"},{"image":"art:c10d55"}]`
    - `image` (string, _required_, pattern: ^(https://|art:|file:).+$) — Any image, as one string: a url, "art:…" or "file:…".
      Example: `https://files.example.com/range_plan.create/1.jpg`
    - `use_case` (string, _optional_) — `fabric`: this image is the row's fabric. Without `use_case`, the image is a detail (a trim, a collar).
      Values: `fabric` (Use this exact fabric: its material, texture and weave. When the design must use exactly this fabric.)
      Example: `fabric`

## Required-fields example

```json
{
  "kind": "new_designs",
  "gender": "womenswear",
  "moodboards": [
    "moodboard:5b3d2c1a-7e6f-4a8b-9c0d-1e2f3a4b5c6d"
  ],
  "garments": [
    {
      "garment_type": "jackets"
    }
  ]
}
```

## Full example

```json
{
  "kind": "new_designs",
  "name": "SS27 capsule",
  "gender": "womenswear",
  "moodboards": [
    "moodboard:5b3d2c1a-7e6f-4a8b-9c0d-1e2f3a4b5c6d"
  ],
  "brand_kit": "brand_kit:28",
  "brands": [
    "Jacquemus"
  ],
  "garments": [
    {
      "garment_type": "jackets",
      "image_count": 4,
      "prompt": "boxy, cropped, raw hems",
      "references": [
        {
          "image": "https://files.example.com/range_plan.create/1.jpg",
          "use_case": "fabric"
        },
        {
          "image": "art:c10d55"
        }
      ]
    },
    {
      "garment_type": "linen wrap skirt",
      "image_count": 2
    }
  ],
  "resolution": "2K"
}
```

## Output schema

- `files` (array<object>, _optional_) — ONE file: the plan, `range_plan:<id>` (`application/json`). Its `data.items` are the plan's cells, `type: design`, each named by its garment line (`garment_type`) or by the prompt you sent for a runway look, with its image `url`; a cell that failed carries `status: failed`. Read it again with `GET /v1/files/range_plan:<id>`.
- `summary` (object, _optional_) — How many cells the plan has, how many have an image, and a warning when some have none.
  - `requested` (integer, _optional_) — How many cells the plan has.
  - `delivered` (integer, _optional_) — How many cells have an image (generated or already made).
  - `warnings` (array<object>, _optional_) — One `{code, field, message}` row when some cells have no image (`code: "output_not_produced"`, `field: "items"`); those cells are in the plan with `status: failed`.

## Response example

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

## Result example

```json
{
  "job_id": "5f0c2a1e9b8d4c7a8e6f1d2c3b4a5968",
  "files": [
    {
      "file": "range_plan:crp_5f0c2a1e9b8d",
      "url": "https://files.example.com/range_plan.create/2.png",
      "media_type": "application/json",
      "task": "range_plan.create",
      "job_id": "5f0c2a1e9b8d4c7a8e6f1d2c3b4a5968",
      "created_at": "2026-09-30T10:14:02Z",
      "data": {
        "name": "SS27 capsule",
        "status": "ready",
        "items": [
          {
            "type": "design",
            "name": "jackets",
            "url": "https://files.example.com/range_plan.create/3.png"
          },
          {
            "type": "design",
            "name": "jackets",
            "url": "https://files.example.com/range_plan.create/4.png"
          },
          {
            "type": "design",
            "name": "jackets",
            "url": "https://files.example.com/range_plan.create/5.png"
          },
          {
            "type": "design",
            "name": "jackets",
            "url": "https://files.example.com/range_plan.create/6.png"
          },
          {
            "type": "design",
            "name": "linen wrap skirt",
            "url": "https://files.example.com/range_plan.create/7.png"
          },
          {
            "type": "design",
            "name": "linen wrap skirt",
            "status": "failed"
          }
        ]
      }
    }
  ],
  "has_more": false,
  "summary": {
    "requested": 6,
    "delivered": 5,
    "warnings": [
      {
        "code": "output_not_produced",
        "field": "items",
        "message": "1 of the plan's 6 cells have no image; they are in the plan with status failed."
      }
    ]
  }
}
```

A runway-looks plan takes `kind: runway_looks` and `looks: [{"image": <a look url from a moodboard's data.items>, "prompt": "the trench coat"}]` instead of `garments` and `brand_kit`.

## Built for

- A season's line plan from your trend boards
- Key garments isolated from runway looks
- New designs per garment line, in your brand's look

## What you get

- One `range_plan:` record; its `data.items` are the plan's cells, each named by its garment line or your look's prompt, with its image `url`.
- A `summary` that counts the plan's cells and the cells with an image, and warns when some have none.

## Specs

- **Input formats:** Images, each one string: a URL, an upload (`file:…`) or a file from an earlier result (`art:…`). Upload types and sizes: `GET /v1/meta` `limits.upload`.
- **Input count:** `looks`: at least 1, each with its image; `garments`: at least 1, each with its image
- **Output format:** One `range_plan:` record: its `data` is JSON in the record vocabulary, its `url` a preview image.
- **Output resolution:** `2K`, `4K`
- **Outputs per job:** One record file, however many cells the plan has.

## Errors

- `field_not_accepted`
- `field_not_supported`
- `invalid_option`
- `invalid_request`
- `moodboard_required`
- `not_found`
- `moodboard_not_ready`
- `look_not_in_moodboard`
- `too_many_references`
- `request_refused`
- `insufficient_credits`
- `permission_denied`
- `processing_failed`

## Related

- `moodboard.create` — It runs before: its result is this input.
- `brand_kit.create` — It runs before: its result is this input.

## Good to know

- `moodboards` holds at least 1 items.
- `looks` holds at least 1 items.
- `garments` holds at least 1 items.
- `garments[].image_count` is from 1 to 20.
- `garments[].references` holds at most 4 items.
- `looks` is taken only with `kind: runway_looks`.
- `garments` is taken only with `kind: new_designs`.
- `brand_kit` is taken only with `kind: new_designs`.

## For agents and code generation

- https://api.refabric.com/v1/tasks/range_plan.create/llms.txt
- https://api.refabric.com/v1/tasks/range_plan.create/openapi.json
- GET https://api.refabric.com/v1/tasks/range_plan.create
