> ## Documentation Index
> Fetch the complete documentation index at: https://sudomock.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The base URL is https://api.sudomock.com.
> Authenticate every request with the x-api-key header. Keys begin with sm_.
> A render returns the finished image at data.print_files[0].export_path. A request sent with is_async true returns a job_id to poll at GET /api/v1/jobs/{job_id}.
> Prefer the official SDKs over hand-written HTTP calls: npm install sudomock for Node, pip install sudomock for Python.

# Group mockups into folders

> Keep a large mockup library in a tree.

A folder holds mockups and other folders. Every mockup sits in exactly one
folder, or at the top of the library, and folders nest, so a library of several
hundred templates reads like a set of drawers instead of one long list. PSD
mockups and photo mockups live in the same tree.

Folders are free. Creating, reading, moving and deleting them costs no credits.

Reach for them when you need to:

* **Keep one brand together**: a folder per customer or per store, so a render
  job only ever looks at the templates that belong to it.
* **Hand a batch to an agent**: point it at one folder instead of asking it to
  guess from names.
* **Split a catalogue**: by season, product type or size, at whatever depth the
  catalogue already has.

## Where a mockup lives

* A mockup is in one folder, or in none. There is no second place.
* Folders nest up to 100 levels, counting the folder you are moving and
  everything inside it.
* Two folders beside each other cannot share a name, whatever the
  capitalisation. The same create call can therefore be made twice without
  building a second copy.
* Moving never changes a mockup's id. Renders, webhooks and every integration
  keep working against the id they already hold.

`folder_uuid` reads three ways, and the difference matters on every list call:

| Value | Meaning |
| - | - |
| left out | Every mockup, wherever it sits. |
| `root` | Only the mockups at the top of the library. |
| a uuid | Only the mockups directly in that folder. |

The same three readings apply to `parent_uuid` when you list folders.

## Create a folder

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "https://api.sudomock.com/api/v1/folders" \
  -H "x-api-key: sm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Frames"
  }'
```

```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "success": true,
  "data": {
    "uuid": "c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061",
    "name": "Frames",
    "parent_uuid": null,
    "folder_count": 0,
    "psd_mockup_count": 0,
    "photo_mockup_count": 0
  }
}
```

Send `parent_uuid` to create it inside another folder instead:

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "https://api.sudomock.com/api/v1/folders" \
  -H "x-api-key: sm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "8x10",
    "parent_uuid": "c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061"
  }'
```

## Walk the tree

[List folders](https://sudomock.com/docs/api-reference/folders/retrieve-a-list-of-folders.md) pages the
same way the mockup lists do, with `limit` and `offset`, and sorts by name.

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl "https://api.sudomock.com/api/v1/folders?parent_uuid=root" \
  -H "x-api-key: sm_your_api_key"
```

Each folder carries `folder_count`, `psd_mockup_count` and
`photo_mockup_count` for what it holds directly, which is enough to draw a
tree without a second call per node.

[Get folder](https://sudomock.com/docs/api-reference/folders/retrieve-a-single-folder.md) adds two things
the list does not: `path`, the trail of folders above this one, and the
`total_` counts for everything inside it at any depth.

## List what is in a folder

Both mockup lists take `folder_uuid`.

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl "https://api.sudomock.com/api/v1/psd-mockups?folder_uuid=root" \
  -H "x-api-key: sm_your_api_key"
```

Swap in `/api/v1/photo-mockups` for the photo mockup side. Every mockup in
either list now carries its own `folder_uuid`, so a single page of results
tells you where each template sits.

## Move mockups and folders

[Move into folder](https://sudomock.com/docs/api-reference/folders/move-mockups-and-folders-into-a-folder.md)
takes any mix of PSD mockups, photo mockups and folders in one call. Either
everything in the call moves or nothing does, so a half finished move is not a
state you have to handle.

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "https://api.sudomock.com/api/v1/folders/move" \
  -H "x-api-key: sm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "target_folder_uuid": "c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061",
    "psd_mockup_uuids": [
      "8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8"
    ]
  }'
```

Send `"target_folder_uuid": null` to move the selection back to the top of the
library. A folder moves with everything inside it. Each list takes up to 500
ids.

To move a single mockup you can also patch it directly:

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X PATCH \
  "https://api.sudomock.com/api/v1/psd-mockups/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8" \
  -H "x-api-key: sm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "folder_uuid": "c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061"
  }'
```

A field you leave out is left alone. `"folder_uuid": null` moves the mockup to
the top of the library.

## Start a mockup inside a folder

Both engines accept `folder_uuid` at creation, so a new template lands where it
belongs without a second call.

```bash PSD mockup theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "https://api.sudomock.com/api/v1/psd/upload" \
  -H "x-api-key: sm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "psd_file_url": "https://example.com/frame.psd",
    "psd_name": "Oak frame 8x10",
    "folder_uuid": "c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061"
  }'
```

```bash Photo mockup theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "https://api.sudomock.com/api/v1/photo-mockups" \
  -H "x-api-key: sm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "source_url": "https://example.com/frame-photo.jpg",
    "name": "Oak frame on a wall",
    "folder_uuid": "c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061"
  }'
```

## Rename or move one folder

[Update folder](https://sudomock.com/docs/api-reference/folders/rename-or-move-a-folder.md) renames a
folder, moves it, or both. A field you leave out is left alone, and
`"parent_uuid": null` moves the folder to the top of the library.

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X PATCH \
  "https://api.sudomock.com/api/v1/folders/c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061" \
  -H "x-api-key: sm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Frames 8x10"
  }'
```

A folder cannot move into itself or into one of its own children, and the tree
it carries counts towards the depth limit at its new home.

## Delete a folder

> [!WARNING]
>
> A recursive delete is permanent. The folders inside go, and so do the mockups
> inside them. There is no recycle bin.

An empty folder deletes on its own. A folder that holds anything needs
`recursive=true`; without it the call is refused with `FOLDER_NOT_EMPTY` and
nothing is touched.

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X DELETE \
  "https://api.sudomock.com/api/v1/folders/c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061?recursive=true" \
  -H "x-api-key: sm_your_api_key"
```

The response says what went:

```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "success": true,
  "data": {
    "deleted": "c4f1a7d2-3b85-4e60-9a1f-7d2c5e8b4061",
    "deleted_folders": 4,
    "deleted_psd_mockups": 12,
    "deleted_photo_mockups": 3
  }
}
```

Read the folder first if you want to tell a person what they are about to lose:
the `total_` counts on
[Get folder](https://sudomock.com/docs/api-reference/folders/retrieve-a-single-folder.md) are exactly the
numbers a recursive delete would remove. A delete that is cut off part way can
be repeated and carries on from where it stopped.

## Errors

| Code | Status | When |
| - | - | - |
| `FOLDER_NOT_FOUND` | 404 | No folder of that id on this account. |
| `FOLDER_NAME_TAKEN` | 409 | A folder beside it already has that name. |
| `FOLDER_NOT_EMPTY` | 409 | The folder holds something and `recursive` was not set. |
| `FOLDER_CYCLE` | 422 | The move would put a folder inside itself. |
| `FOLDER_TOO_DEEP` | 422 | The move would pass the depth limit. |

> [card] [Folders reference](https://sudomock.com/docs/api-reference/folders/retrieve-a-list-of-folders.md)
>
> Every field on every folder call.

> [card] [Pagination](https://sudomock.com/docs/api-reference/pagination.md)
>
> How `limit`, `offset` and `total` behave.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.