# PATCH /api/v2/drive-folders/{drive_folder}

Update a drive folder

- MCP id: drive-folders.update
- Scope: api:write:project_drive
- Scope: api:write:customer_drive
- Scope: api:write:organization_drive
- Scope: api:write:user_drive
- Permission: project_drive::create
- Rate cost: 1 unit, write bucket. A write costs the same whatever `view` you ask for.
- Cache-Control: private, no-store

Partially updates a drive folder: absent keys are untouched, an empty body is rejected.

`name` and `parent_id` are the writable keys: a rename, and a move to another folder within the same drive, which is plnnrly's folder drag-and-drop minus the position. The new parent must belong to the same owner, be a folder you can edit, and be neither this folder nor one of its descendants; `null` moves the folder to the drive root. Moving a folder to a different drive is not possible in v2.0: neither half of the owner pair is accepted on a PATCH, and neither are order, `created_by`, `general_access` or `inherits_permissions`. Send `If-Match` with the `ETag` from your last read to detect a concurrent edit, which answers `412`. Treat it as best-effort only: this resource carries no concurrency token and `updated_at` is second-precision, so two writes inside the same second are indistinguishable. The declared permission is `project_drive::create` (editing is part of the create permission), and it is a superset of what is checked: the record rule needs the owner type's `{owner}_drive::access` plus edit access on the folder, which is exactly what plnnrly enforces.

## Parameters
- drive_folder (integer, path): The DriveFolder's numeric id.
- view (string, optional): Which field set to render.
- X-Request-Id (header, optional): A correlation id of your own. It is recorded in our logs next to the server's request id but never returned: the response header always carries the server's id. A value that does not match the pattern is discarded silently, never rejected.
- If-Match (header, optional): The ETag a write is conditional on. A stale validator is 412 precondition-failed.

## Request body
- name (string ≤ 255, optional): Folder name as shown in the drive tree.
- parent_id (integer or null → DriveFolder.id, optional): Folder this one sits in, or `null` at the drive root.

Unknown keys are refused with `422` validation-failed, naming the key.

## Response 200
- id (integer, required): Unique identifier.
- name (string ≤ 255, required): Folder name as shown in the drive tree.
- parent_id (integer or null, required): Folder this one sits in, or `null` at the drive root.
- parent_folder (Ref or DriveFolderSummary or null, required): The folder this one sits in; absent for folders at the drive root.
- owner_type (string, required): The kind of record `owner` points at; it says which branch of `owner` applies.
- owner_id (integer, required): The id of the record `owner` points at.
- owner (Ref or ProjectSummary or CustomerSummary or UserSummary, required): The project, customer, organisation or user whose drive this folder lives in. An organisation-owned folder renders as a bare {"id": N} reference.
- order (integer, required, server-assigned): Sort position within the drive and level, as shown in the drive tree. Positions count per drive and level, so the sequence is only meaningful once the collection is narrowed to one drive and one level. It is not assigned on create, so a folder created through the API stays at 0 until it is positioned in plnnrly; reordering is not exposed in v2.0.
- created_by (integer or null, required, server-assigned): Author; always the authenticated user at create time. Null on legacy rows and where the author has since been deleted.
- inherits_permissions (boolean, required): Whether this folder takes its permissions from its parent.
- general_access (string, required): Baseline sharing tier, consulted only while `inherits_permissions` is `false`.
- access (string or null, required): The calling user's effective access level on this folder, after the permission for the owner type, the access inherited from folders and any per-folder grant.
- created_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Creation timestamp.
- updated_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Last-write timestamp; use for incremental sync.
- drive_items_count (integer ≥ 0, required): Live drive items directly in this folder that the caller may see. Archived items are not counted, and neither are items in subfolders.
- links (DriveFolderLinks, required)
  - self (url, required): The canonical URI of this record.
  - drive_items (url, required): Drive items directly in this folder.

## Errors
- 403 forbidden-by-policy | insufficient-permission | insufficient-token-scope: Forbidden.
- 412 precondition-failed: Precondition failed.
- 415 unsupported-media-type: Unsupported media type.
- 422 unprocessable-relationship | validation-failed: Unprocessable content.
- 400 idempotency-key-required | invalid-cursor | invalid-query-parameter | malformed-request | unsupported-parameter: Bad request.
- 401 token-expired | unauthenticated: Unauthenticated.
- 404 endpoint-not-found | resource-not-found: Not found.
- 406 not-acceptable: Not acceptable.
- 429 rate-limit-exceeded: Too many requests.
- 500 internal-error: Server error.
- 503 tenant-unavailable: Service unavailable.

## Example
```bash
curl -X PATCH \
  'https://<your-url>/api/v2/drive-folders/1' \
  -H 'Authorization: Bearer <token>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'If-Match: *' \
  -d '{
    "name": "Kick-off (archive)",
    "parent_id": null
  }'
```
