<!-- section: Files API · status: building · source: docs/files-api/04-update-files.md -->

> Change visibility, ownership, position or transform settings — and what moves when you do.


# Update files

## PATCH /v1/files/{id}

Every field is optional; send only what changes.

```json Request body
{
  "visibility": "private",              // Moves the object — see below
  "ownerUserId": "user_456",            // Or null to clear it
  "position": 2,                        // Order within its entity role
  "transformations": {
    "image": {
      "enabled": true,
      "visibility": "public"            // Changing this purges existing sizes
    }
  }
}
```

```json Response
{ "file": { "…": "the file in its new state, with fresh URLs" } }
```

## Visibility moves the object

Visibility is a path prefix, not a flag, because the prefix is what the CDN's
signing policy keys on. A flag would leave the edge serving the file exactly as
before — the failure you would least want to discover.

So changing it **moves the object**, and two things follow:

- **The URL changes.** Any public URL you cached is now a `404`. This is the one
  case that breaks the "public URLs are permanent" rule, and it breaks it
  because you asked.
- **It is not instant at the edge.** An already-cached copy can still be served
  for a while. Treat public → private as *no longer distributed* rather than
  *immediately unreachable*; if it must be unreachable now,
  [delete it](/docs/files-api/delete-files).

## Variant visibility purges the sizes

Variants live under their own prefix too, so switching
`transformations.image.visibility` deletes the ones that exist. They rebuild on
demand under the new prefix, the first time each is requested. Leaving them
would be bytes nobody can reach and everybody pays for.

## Errors

```json 400
{ "error": "Visibility must be 'public' or 'private'" }
```

```json 404
{ "error": "File not found" }
```

## What you cannot change

- **A file's contents.** Upload a new one and delete the old.
- **Its filename.** Derived at upload and fixed; `originalFilename` is what you
  were displaying anyway.
- **Its project.** Files belong to the project that uploaded them.
