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

# Folders

> Create, list, retrieve, update, and delete folders. Folders nest via parent_id and can carry optional AI-steering context.

Folders organize your diagrams. They nest into trees through `parent_id`, and each folder can hold an optional `context` string that steers AI generation for diagrams created inside it.

<Note>
  All requests run **server-to-server** over HTTPS and authenticate with an API key. Never expose a key in a browser or client app. See [Authentication](/api-reference/authentication) for details.
</Note>

## The Folder object

<ResponseField name="object" type="string">
  Always `"folder"`.
</ResponseField>

<ResponseField name="id" type="string">
  UUID of the folder.
</ResponseField>

<ResponseField name="name" type="string">
  Display name of the folder.
</ResponseField>

<ResponseField name="parent_id" type="string | null">
  UUID of the parent folder, or `null` if the folder lives at the root. This is how folders nest.
</ResponseField>

<ResponseField name="context" type="string | null">
  Optional free-text context used to steer AI generation for diagrams in this folder. `null` when unset.
</ResponseField>

<ResponseField name="organization_id" type="string | null">
  UUID of the owning organization for org keys, or `null` for personal keys.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO-8601 UTC timestamp of creation.
</ResponseField>

<ResponseField name="updated_at" type="string">
  ISO-8601 UTC timestamp of the last update.
</ResponseField>

```json The Folder object theme={null}
{
  "object": "folder",
  "id": "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c",
  "name": "Onboarding processes",
  "parent_id": null,
  "context": "Customer onboarding for a B2B SaaS. Prefer swimlanes per department.",
  "organization_id": null,
  "created_at": "2026-06-01T12:00:00Z",
  "updated_at": "2026-06-01T12:00:00Z"
}
```

## Endpoints

<CardGroup cols={2}>
  <Card title="List folders" icon="list" href="#list-folders">
    `GET /v1/folders`
  </Card>

  <Card title="Create a folder" icon="folder-plus" href="#create-a-folder">
    `POST /v1/folders`
  </Card>

  <Card title="Retrieve a folder" icon="magnifying-glass" href="#retrieve-a-folder">
    `GET /v1/folders/{id}`
  </Card>

  <Card title="Update a folder" icon="pen" href="#update-a-folder">
    `PATCH /v1/folders/{id}`
  </Card>

  <Card title="Delete a folder" icon="trash" href="#delete-a-folder">
    `DELETE /v1/folders/{id}`
  </Card>
</CardGroup>

***

## List folders

```http theme={null}
GET /v1/folders
```

Returns a cursor-paginated list of folders, **newest first** (`created_at` descending). Requires the `folders:read` scope.

### Query parameters

<ParamField query="limit" type="integer">
  Number of folders to return. Integer between `1` and `100`. Defaults to `20`.
</ParamField>

<ParamField query="cursor" type="string">
  Opaque pagination cursor. Pass the `next_cursor` from a previous response to fetch the next page. An invalid or expired cursor returns `400 invalid_cursor`.
</ParamField>

### Response

<ResponseField name="data" type="array">
  Array of [Folder](#the-folder-object) objects.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  `true` if more folders are available beyond this page.
</ResponseField>

<ResponseField name="next_cursor" type="string | null">
  Cursor to pass as `cursor` for the next page, or `null` on the last page.
</ResponseField>

<CodeGroup>
  ```bash curl theme={null}
  curl https://justflow.it/api/v1/folders?limit=20 \
    -H "Authorization: Bearer jfi_sk_live_..."
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://justflow.it/api/v1/folders?limit=20", {
    headers: { Authorization: "Bearer jfi_sk_live_..." },
  });
  const page = await res.json();
  ```

  ```python Python theme={null}
  import requests

  res = requests.get(
      "https://justflow.it/api/v1/folders",
      params={"limit": 20},
      headers={"Authorization": "Bearer jfi_sk_live_..."},
  )
  page = res.json()
  ```
</CodeGroup>

```json 200 OK theme={null}
{
  "data": [
    {
      "object": "folder",
      "id": "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c",
      "name": "Onboarding processes",
      "parent_id": null,
      "context": "Customer onboarding for a B2B SaaS. Prefer swimlanes per department.",
      "organization_id": null,
      "created_at": "2026-06-01T12:00:00Z",
      "updated_at": "2026-06-01T12:00:00Z"
    },
    {
      "object": "folder",
      "id": "1d2c3b4a-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "name": "Q2 audit subprocesses",
      "parent_id": "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c",
      "context": null,
      "organization_id": null,
      "created_at": "2026-05-28T09:15:00Z",
      "updated_at": "2026-05-28T09:15:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

<Tip>
  To walk every page, keep calling with `cursor=next_cursor` until `has_more` is `false`.
</Tip>

***

## Create a folder

```http theme={null}
POST /v1/folders
```

Creates a new folder. Requires the `folders:write` scope. Returns `201 Created` with a `Location` header pointing at the new folder.

### Body parameters

<ParamField body="name" type="string" required>
  Display name of the folder.
</ParamField>

<ParamField body="parent_id" type="string | null">
  UUID of the parent folder to nest under. Omit or set to `null` to create the folder at the root.
</ParamField>

<ParamField body="context" type="string">
  Optional free-text context that steers AI generation for diagrams created inside this folder.
</ParamField>

<CodeGroup>
  ```bash curl theme={null}
  curl https://justflow.it/api/v1/folders \
    -H "Authorization: Bearer jfi_sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Onboarding processes",
      "parent_id": null,
      "context": "Customer onboarding for a B2B SaaS. Prefer swimlanes per department."
    }'
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://justflow.it/api/v1/folders", {
    method: "POST",
    headers: {
      Authorization: "Bearer jfi_sk_live_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Onboarding processes",
      parent_id: null,
      context:
        "Customer onboarding for a B2B SaaS. Prefer swimlanes per department.",
    }),
  });
  const folder = await res.json();
  ```

  ```python Python theme={null}
  import requests

  res = requests.post(
      "https://justflow.it/api/v1/folders",
      headers={
          "Authorization": "Bearer jfi_sk_live_...",
          "Content-Type": "application/json",
      },
      json={
          "name": "Onboarding processes",
          "parent_id": None,
          "context": "Customer onboarding for a B2B SaaS. Prefer swimlanes per department.",
      },
  )
  folder = res.json()
  ```
</CodeGroup>

```json 201 Created theme={null}
{
  "object": "folder",
  "id": "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c",
  "name": "Onboarding processes",
  "parent_id": null,
  "context": "Customer onboarding for a B2B SaaS. Prefer swimlanes per department.",
  "organization_id": null,
  "created_at": "2026-06-01T12:00:00Z",
  "updated_at": "2026-06-01T12:00:00Z"
}
```

<Tip>
  Use `context` to pass domain knowledge once (industry, conventions, terminology) so every diagram generated into the folder inherits that steering.
</Tip>

***

## Retrieve a folder

```http theme={null}
GET /v1/folders/{id}
```

Returns a single folder by id. Requires the `folders:read` scope. An unknown id returns `404 resource_not_found`.

### Path parameters

<ParamField path="id" type="string" required>
  UUID of the folder to retrieve.
</ParamField>

<CodeGroup>
  ```bash curl theme={null}
  curl https://justflow.it/api/v1/folders/8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c \
    -H "Authorization: Bearer jfi_sk_live_..."
  ```

  ```javascript JavaScript theme={null}
  const id = "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c";
  const res = await fetch(`https://justflow.it/api/v1/folders/${id}`, {
    headers: { Authorization: "Bearer jfi_sk_live_..." },
  });
  const folder = await res.json();
  ```

  ```python Python theme={null}
  import requests

  folder_id = "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c"
  res = requests.get(
      f"https://justflow.it/api/v1/folders/{folder_id}",
      headers={"Authorization": "Bearer jfi_sk_live_..."},
  )
  folder = res.json()
  ```
</CodeGroup>

```json 200 OK theme={null}
{
  "object": "folder",
  "id": "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c",
  "name": "Onboarding processes",
  "parent_id": null,
  "context": "Customer onboarding for a B2B SaaS. Prefer swimlanes per department.",
  "organization_id": null,
  "created_at": "2026-06-01T12:00:00Z",
  "updated_at": "2026-06-01T12:00:00Z"
}
```

***

## Update a folder

```http theme={null}
PATCH /v1/folders/{id}
```

Updates the supplied fields on a folder. Requires the `folders:write` scope. Send any subset of the body fields; omitted fields are left unchanged. Returns `200 OK` with the updated folder.

### Path parameters

<ParamField path="id" type="string" required>
  UUID of the folder to update.
</ParamField>

### Body parameters

<ParamField body="name" type="string">
  New display name.
</ParamField>

<ParamField body="context" type="string">
  New AI-steering context.
</ParamField>

<ParamField body="parent_id" type="string | null">
  New parent folder UUID, or `null` to move the folder to the root.
</ParamField>

<CodeGroup>
  ```bash curl theme={null}
  curl -X PATCH https://justflow.it/api/v1/folders/8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c \
    -H "Authorization: Bearer jfi_sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{ "name": "Onboarding (2026)", "parent_id": null }'
  ```

  ```javascript JavaScript theme={null}
  const id = "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c";
  const res = await fetch(`https://justflow.it/api/v1/folders/${id}`, {
    method: "PATCH",
    headers: {
      Authorization: "Bearer jfi_sk_live_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ name: "Onboarding (2026)", parent_id: null }),
  });
  const folder = await res.json();
  ```

  ```python Python theme={null}
  import requests

  folder_id = "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c"
  res = requests.patch(
      f"https://justflow.it/api/v1/folders/{folder_id}",
      headers={
          "Authorization": "Bearer jfi_sk_live_...",
          "Content-Type": "application/json",
      },
      json={"name": "Onboarding (2026)", "parent_id": None},
  )
  folder = res.json()
  ```
</CodeGroup>

```json 200 OK theme={null}
{
  "object": "folder",
  "id": "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c",
  "name": "Onboarding (2026)",
  "parent_id": null,
  "context": "Customer onboarding for a B2B SaaS. Prefer swimlanes per department.",
  "organization_id": null,
  "created_at": "2026-06-01T12:00:00Z",
  "updated_at": "2026-06-07T10:42:00Z"
}
```

***

## Delete a folder

```http theme={null}
DELETE /v1/folders/{id}
```

Deletes a folder. Requires the `folders:write` scope. Returns `204 No Content` with an empty body.

### Path parameters

<ParamField path="id" type="string" required>
  UUID of the folder to delete.
</ParamField>

<CodeGroup>
  ```bash curl theme={null}
  curl -X DELETE https://justflow.it/api/v1/folders/8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c \
    -H "Authorization: Bearer jfi_sk_live_..."
  ```

  ```javascript JavaScript theme={null}
  const id = "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c";
  const res = await fetch(`https://justflow.it/api/v1/folders/${id}`, {
    method: "DELETE",
    headers: { Authorization: "Bearer jfi_sk_live_..." },
  });
  // res.status === 204
  ```

  ```python Python theme={null}
  import requests

  folder_id = "8b1f6c2e-3a4d-4e9b-9c1a-2f7d8e0a5b3c"
  res = requests.delete(
      f"https://justflow.it/api/v1/folders/{folder_id}",
      headers={"Authorization": "Bearer jfi_sk_live_..."},
  )
  # res.status_code == 204
  ```
</CodeGroup>

```http 204 No Content theme={null}
HTTP/1.1 204 No Content
X-Request-Id: req_8f3c2a1b9d7e
```

***

## Errors

Every error uses the standard envelope. The `type` maps to the HTTP status, and every response carries an `X-Request-Id` header (mirrored as `request_id` in the body).

```json Error envelope theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "missing_parameter",
    "message": "Missing required parameter: name.",
    "param": "name"
  },
  "request_id": "req_8f3c2a1b9d7e"
}
```

<AccordionGroup>
  <Accordion title="400 — invalid_request_error">
    Codes: `invalid_json`, `missing_parameter`, `invalid_parameter`, `payload_too_large`, `invalid_cursor`. Returned when `name` is missing on create, a field is malformed, or a pagination `cursor` is invalid or expired.
  </Accordion>

  <Accordion title="401 — authentication_error">
    Codes: `missing_api_key`, `invalid_api_key`, `revoked_api_key`, `expired_api_key`. Responses include a `WWW-Authenticate: Bearer` header.
  </Accordion>

  <Accordion title="403 — permission_error">
    Codes: `plan_required` (the API is paid-plans only), `insufficient_scope` (the key lacks `folders:read` or `folders:write`).
  </Accordion>

  <Accordion title="404 — not_found_error">
    Code: `resource_not_found`. The folder id does not exist or is not accessible to your key.
  </Accordion>

  <Accordion title="429 — rate_limit_error">
    Codes: `rate_limit_exceeded`, `quota_exceeded`. Responses include a `Retry-After` header (seconds). The per-key burst limit is 120 requests / 60s.
  </Accordion>

  <Accordion title="500 — api_error">
    Code: `internal_error`. Something failed on our side. Retry with backoff and include the `request_id` if you contact support.
  </Accordion>
</AccordionGroup>

<Warning>
  Folder endpoints fail with `403 insufficient_scope` if your key is missing the right scope: reads need `folders:read`, writes (create / update / delete) need `folders:write`.
</Warning>
