# Rename or move a folder

**PUT** `/api/folders/{id}`

Renames a folder, moves it, or both, in one write.

Needs [an API token](https://docs.gorunner.io/api/authentication#scopes) with the **Write** permission for workflows (`workflow:write`).

> **Warning** Send `parentId` every time. Leaving it out moves the folder to the top level. To rename in place, send its current `parentId`.

## Parameters

### Path

- `id` · Required · UUID: The folder’s ID.

### Body

- `name` · Required · string: The name, new or the same. Up to 255 characters, trimmed, and different from the other folders in that place.
- `parentId` · Optional · UUID: Where the folder goes, exactly as sent: `null` or left out is the top level. Not the folder itself or a folder inside it.

## Responses

- 200 OK

  Done. The answer doesn’t hold the folder: list the folders to see it.

- 400 `VALIDATION_ERROR`

  The ID isn’t a UUID, the body isn’t JSON, or the name is blank or over 255 characters.

- 400 `VALIDATION_ERROR`

  The new place is the folder itself, a folder inside it, or not a folder in this workspace.

- 403 `FORBIDDEN`

  The token lacks the **Write** permission for workflows.

- 404 `NOT_FOUND`

  No folder with this ID in the workspace.

- 409 `NAME_TAKEN`

  A folder with this name is already in that place. Names are compared without case.

- 500 `INTERNAL_ERROR`

  Nothing changed. Try again.

Any call can also answer: [`401 UNAUTHORIZED`](https://docs.gorunner.io/errors#UNAUTHORIZED) · [`401 TOKEN_ENDED`](https://docs.gorunner.io/errors#TOKEN_ENDED) · [`403 TOKEN_SURFACE_OFF`](https://docs.gorunner.io/errors#TOKEN_SURFACE_OFF) · [`403 FEATURE_OFF`](https://docs.gorunner.io/errors#FEATURE_OFF) · [`403 EMBED_NOT_ALLOWED`](https://docs.gorunner.io/errors#EMBED_NOT_ALLOWED) · [`403 EMBED_NOT_AVAILABLE`](https://docs.gorunner.io/errors#EMBED_NOT_AVAILABLE) · [`403 ACCOUNT_SUSPENDED`](https://docs.gorunner.io/errors#ACCOUNT_SUSPENDED) · [`413 PAYLOAD_TOO_LARGE`](https://docs.gorunner.io/errors#PAYLOAD_TOO_LARGE) · [`415 INVALID_CONTENT_TYPE`](https://docs.gorunner.io/errors#INVALID_CONTENT_TYPE) · [`429 RATE_LIMITED`](https://docs.gorunner.io/errors#RATE_LIMITED) · [`503 BUSY`](https://docs.gorunner.io/errors#BUSY) · [`503 PAUSED`](https://docs.gorunner.io/errors#PAUSED) · [`503 SERVICE_UNAVAILABLE`](https://docs.gorunner.io/errors#SERVICE_UNAVAILABLE). See [Errors](https://docs.gorunner.io/api/errors#by-status).

Request

**curl**

```bash
GORUNNER="https://api.gorunner.io"
GORUNNER_TOKEN="grt_…"  # needs Write for workflows
FOLDER_ID="your-folder-id"

curl -X PUT "$GORUNNER/api/folders/$FOLDER_ID" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invoices 2026",
    "parentId": "7a2c9e41-5b3d-4f08-a6e1-2d9c4b7f0e13"
  }'
```

**JavaScript**

```js
const GORUNNER = "https://api.gorunner.io";
const TOKEN = process.env.GORUNNER_TOKEN;
const FOLDER_ID = process.env.FOLDER_ID;

const res = await fetch(
  `${GORUNNER}/api/folders/${FOLDER_ID}`,
  {
    method: "PUT",
    headers: {
        Authorization: `Bearer ${TOKEN}`,
        "Content-Type": "application/json",
      },
    body: JSON.stringify({
        name: "Invoices 2026",
        parentId: "7a2c9e41-5b3d-4f08-a6e1-2d9c4b7f0e13",
      }),
  },
);
const { data } = await res.json();
```

**Python**

```python
import os, requests

GORUNNER = "https://api.gorunner.io"
TOKEN = os.environ["GORUNNER_TOKEN"]
FOLDER_ID = os.environ["FOLDER_ID"]

res = requests.put(
    f"{GORUNNER}/api/folders/{FOLDER_ID}",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={
      "name": "Invoices 2026",
      "parentId": "7a2c9e41-5b3d-4f08-a6e1-2d9c4b7f0e13",
    },
)
data = res.json()["data"]
```

Response · 200 OK

```json
{
  "data": {
    "id": "6e9a1c3f-8b2d-4a57-9e0c-3f7b5d1a8c42",
    "updated": true
  }
}
```

**Every field**

### Body

- `name` · Required · string: Required; trimmed. Blank, or longer than 255 characters, is a 400. A name another folder in the new place already has, ignoring case, is a 409 `NAME_TAKEN`.
- `parentId` · Optional · UUID: The new parent, applied EXACTLY as sent. Omitting it (or sending null) MOVES THE FOLDER TO THE ROOT — to rename without moving, re-send the folder’s current `parentId`. Cannot be the folder itself or one of its descendants.

### Response · 200 OK

- `data` · object: Bare acknowledgement returned by folder update and delete. It does NOT contain the folder — re-list if you need the new state.
  - `id` · UUID: The folder the operation applied to.
  - `updated` · boolean: Always true; present on the update response only.
  - `deleted` · boolean: Always true; present on the delete response only.

Related: [List folders](https://docs.gorunner.io/api/folders/list-folders) · [Delete a folder](https://docs.gorunner.io/api/folders/delete-folder)

Source: https://docs.gorunner.io/api/folders/update-folder
