---
title: "Import presets"
method: POST
path: "/api/v1/presets/import"
tags: ["Preset Management"]
---

# Import presets

`POST /api/v1/presets/import`

## Request

- Base URL: `https://api.imagestep.dev`
- URL: `https://api.imagestep.dev/api/v1/presets/import`
- Auth: API key in header `Authorization`

Takes the list `GET /api/v1/presets?filter=user&includeVersions=true` returns — without
`includeVersions` the rows carry no history — or any list of preset documents. `version` and
`versions` are kept as exported (version defaults to 1), so an imported preset replays its
history. Each entry is checked like a create; one that fails is reported in `errors` and the rest
still land, so a `201` can carry refusals — read `errors`. A slug already in use gets a numeric
suffix instead of being refused.

LIMITS: the whole import is refused (`422 resource_limit_exceeded`) if it would take the account past 1000 presets; an entry carrying more than 50 versions is reported in `errors` and the rest still land.

## Headers

- `Idempotency-Key` string

## Request body

- PresetData[]
  - `id` string: Preset id (`pre_…`; a built-in's starts with `builtin-`). A job's `presetId` takes it, the slug, or either with `@version`.
  - `name` string: Display name (required on create).
  - `slug` string: URL-safe handle, unique per account: lowercase letters, digits and hyphens. Generated from the name when absent (a numeric suffix keeps it unique); one you send must be free. `builtin-` is reserved.
  - `description` string: Free text for people; not run. `""` on a PUT empties it.
  - `subjects` Subject[]: What has to look the same every time: each subject is `{name, referenceAssetIds, descriptor}`, at most 4 of them. The images (max 4 across all subjects, your own, status DONE) ride along on the preset's generate / edit step and pin the geometry; the descriptor expands into its prompt wherever you write `{{subject.<name>}}`. A preset with subjects needs a generate or edit step.
    - `name` string: Lowercase handle (`[a-z0-9][a-z0-9_-]{0,39}`, unique among the subjects), referenced in a prompt as {{subject.<name>}}.
    - `referenceAssetIds` string[]: Your own DONE asset ids showing this subject. They pin the geometry.
    - `descriptor` string: The locked description — colour, material, markings — at most 300 characters. Text pins what an image cannot show.
  - `steps` PresetStep[]: The steps, run in order. Each is `{op, model?, prompt?, parameters?}` (an op from GET /api/v1/ops) or `{operation, params}` (a processing-registry key, for what no op covers). Checked when written: a parameter outside its op's contract is 400 invalid_param on `steps[i].parameters.<name>`. Adjacent deterministic steps run as one `process` pass and each AI step as its op's own job; those are the preset's segments. One segment runs as that job; more than one — an AI step beside other steps, or several AI steps — runs as one `chain` job, each item walking the segments in order with the output of one as the input of the next.
    - `op` string: An op from GET /api/v1/ops (kind ai or deterministic).
    - `model` string: AI steps: the model; the op's default when absent.
    - `prompt` string: AI steps: the prompt. {{subject.<name>}} expands to that subject's descriptor.
    - `parameters` object: The op's parameters. A deterministic op's are checked against its catalogue contract when the steps are written, and so are `analyze`'s bounds; an AI image op's go to the model as sent.
    - `operation` string: A processing-registry key (deterministic only), for steps no op covers.
    - `params` object: That registry step's arguments.
  - `version` integer: Starts at 1 and goes up whenever `steps` or `subjects` change; a name, description or slug edit is not a version. Run or read an earlier one as `slug@version` / `?version=N`.
  - `versions` PresetVersion[]: Superseded versions, oldest first. Present in exports so an import replays the same history. GET /api/v1/presets leaves it off unless you ask for `?includeVersions=true` — a list row does not need every snapshot of every preset, and `versionCount` says whether there is any history to read.
    - `version` integer: The version number; `slug@version` runs and reads exactly this.
    - `steps` PresetStep[]: The steps as that version had them.
      - `op` string: An op from GET /api/v1/ops (kind ai or deterministic).
      - `model` string: AI steps: the model; the op's default when absent.
      - `prompt` string: AI steps: the prompt. {{subject.<name>}} expands to that subject's descriptor.
      - `parameters` object: The op's parameters. A deterministic op's are checked against its catalogue contract when the steps are written, and so are `analyze`'s bounds; an AI image op's go to the model as sent.
      - `operation` string: A processing-registry key (deterministic only), for steps no op covers.
      - `params` object: That registry step's arguments.
    - `subjects` Subject[]: The subjects as that version had them.
      - `name` string: Lowercase handle (`[a-z0-9][a-z0-9_-]{0,39}`, unique among the subjects), referenced in a prompt as {{subject.<name>}}.
      - `referenceAssetIds` string[]: Your own DONE asset ids showing this subject. They pin the geometry.
      - `descriptor` string: The locked description — colour, material, markings — at most 300 characters. Text pins what an image cannot show.
    - `updatedAt` string, date-time: When that version was saved.
  - `versionCount` integer: How many versions are on record: the current one plus every superseded one. Always present on a read, whether or not `versions` is, so a list reader can tell a preset with history from one without fetching it.
  - `createdAt` string, date-time: When the preset was created
  - `updatedAt` string, date-time: When the preset was last saved, a rename included — the order your own rows are listed in. On an earlier version read as `slug@N`, when that version was saved.
  - `builtIn` boolean: Whether this is a built-in preset (read-only)
  - `warnings` StepWarning[]: What these steps say that is legal, will run, and is probably not what was meant (imagestep#416): a format a later step shadows, a step the one before it already did. Advisory — the preset was saved. Derived, never stored: a write answers with the findings about what it just saved, and POST /api/v1/jobs?dryRun=true recomputes them for any preset. What could not run at all was refused instead, 400 invalid_param naming the step.
    - `code` string: Machine-readable finding code from a closed set; the table is /docs/presets#warnings
    - `message` string: The finding in one sentence, naming the steps by index
    - `steps` integer[]: The step indexes the finding is about, in order — the redundant one first
  - `usage` PresetUsage: How often this preset has been run, over the jobs still on record — job records expire with the assets they produced, so this is the retention window and not all time. Read-only and derived.
    - `runs` integer: Jobs that ran this preset, at any version, within the retention window.
    - `lastRunAt` string, date-time: When the most recent of them was submitted.

## Response `201`

What landed, and one line per entry that did not

## Other responses

- `400`: `invalid_param` — the body is not a non-empty list
- `409`: Conflict — `error.code` is `idempotency_key_reuse` (the key already means a different request) or `request_in_progress` (the first request under this key has not settled yet; retryable).
- `422`: `resource_limit_exceeded` — the entries would take the account past 1000 presets; nothing was imported
- `429`: Rate limited — `error.code` is `rate_limited` and `retryable` is true. `Retry-After` says how many seconds to wait.

---

[API](https://skmtc.dev/imagestep/apis/imagestep-api.md) · [All operations](https://skmtc.dev/imagestep/apis/imagestep-api/llms.txt) · [OpenAPI document](https://skmtc.dev/imagestep/apis/imagestep-api/revisions/5e8e922a3085?raw)
