---
title: "Write files as one version"
method: PUT
path: "/v2/pens/{id}/files"
tags: ["Files"]
---

# Write files as one version

`PUT /v2/pens/{id}/files`

## Request

- Base URL: `https://api.codepen.io`
- URL: `https://api.codepen.io/v2/pens/{id}/files`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Applies `files` changes, in order, as one saved version and builds it.
Each change addresses a file by `path` or `id`:

| Change | Effect |
| --- | --- |
| `{ path, content }` | Writes the file at `path`, creating it if needed. |
| `{ id, content }` | Writes the file with that id, wherever it is. |
| `{ id, path }` | Moves the file to `path`; it keeps its id. Add `content` to write there too. |
| `{ path, delete: true }` | Deletes the file, or every file under a directory path. |
| `{ id, delete: true }` | Deletes the file with that id. |

Binary files go up as parts of a multipart form, each one more change
applied after those in `changes`.

## Query parameters

- `wait` integer
- `dry_run` boolean

## Request body

- FilesWriteRequest
  - `dry_run` boolean: Build the proposed files without saving them. The head does not move, and the answer's `version` has `saved: false`; it stays readable at `GET /v2/versions/{id}` for 36 hours.
  - `expected_version_id` string: The `saved_version.id` the change was built on. The write is refused with `409` if the Pen's head has moved since.
  - `wait` integer: Seconds to wait for the build (default 45, at most 75; `0` answers as soon as the files are saved).
  - `files` FileChange[]
    - `content` string
    - `delete` boolean
    - `id` string
    - `path` string
  - `label` string: Names the saved version.

## Response `200`

The Pen, the newest version the write produced with its `files`, and that version's build.

- FilesWriteResult
  - `build` Build, required
    - `applied_patches` BuildPatch[], required: Changes the API applied to the caller's files on the compiler's behalf.
      - `content` string, nullable, required: Set for `create` and `update`.
      - `file_id` string, nullable, required: Set for `update` and `delete`.
      - `path` string, required
      - `type` string, required: `create`, `update` or `delete`.
    - `diagnostics` BuildDiagnostic[], required: Every diagnostic of the final build.
      - `block_name` string, nullable, required
      - `code` string, nullable, required
      - `file_id` string, nullable, required
      - `message` string, required
      - `path` string, nullable, required
      - `range` FileRange, required
        - `end` FileLocation, required
          - `column` integer, required
          - `line` integer, required
          - `position` integer, nullable, required
        - `start` FileLocation, required
          - `column` integer, required
          - `line` integer, required
          - `position` integer, nullable, required
      - `scope` 'Build' | 'BuildStep' | 'File', required
      - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
      - `url` string, nullable, required
    - `ended_at` string, date-time, nullable, required
    - `errors` BuildDiagnostic[], required: The diagnostics with `type` `Error`.
      - `block_name` string, nullable, required
      - `code` string, nullable, required
      - `file_id` string, nullable, required
      - `message` string, required
      - `path` string, nullable, required
      - `range` FileRange, required
        - `end` FileLocation, required
          - `column` integer, required
          - `line` integer, required
          - `position` integer, nullable, required
        - `start` FileLocation, required
          - `column` integer, required
          - `line` integer, required
          - `position` integer, nullable, required
      - `scope` 'Build' | 'BuildStep' | 'File', required
      - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
      - `url` string, nullable, required
    - `files` File[]: The compiled output served under the version's `preview_url`. On the single version and build endpoints and the writes, and only when the build succeeded.
      - `bytes` integer, required
      - `content` string, nullable, required: Null for binary files, which are read from `url`.
      - `content_hash` string, required
      - `content_type` string, required: The media type the file is served with, from its extension.
      - `download_url` string, uri, nullable, required: The file's exact bytes for anyone holding the URL, on the API host (`GET /v2/pens/{id}/download/{path}`), for one hour from this response: no API key, session or Referer needed. Served as an attachment with the file's `content_type`. A new URL comes with every read; an expired one answers `403`. Null for the files of a Pen made in the classic editor.
      - `id` string, required: Stable across versions, renames and edits.
      - `is_binary` boolean, required
      - `name` string, required
      - `path` string, required
      - `url` string, uri, nullable, required: Where the file is served raw on the Pen's content domain. It follows the Pen's own access rules: a Private, Protected or Collaborators Pen needs a browser session and a Pen owned by a Free account needs a CodePen Referer, neither of which an API client has, so read files through `content` or `download_url`. Null for the files of a Pen made in the classic editor.
    - `id` string, required: The version's id, before and after the version is saved.
    - `next_id` string, nullable, required: The build applying this one's patches.
    - `patches` BuildPatch[], required: Changes the compiler still requires.
      - `content` string, nullable, required: Set for `create` and `update`.
      - `file_id` string, nullable, required: Set for `update` and `delete`.
      - `path` string, required
      - `type` string, required: `create`, `update` or `delete`.
    - `previous_id` string, nullable, required: The caller's build this one was converged from.
    - `rounds` integer, required: How many compiler builds it took, counted from the version the caller wrote.
    - `started_at` string, date-time, nullable, required
    - `status` 'Queued' | 'Running' | 'Success' | 'Failed' | 'Canceled', required: `Canceled` means changes are still required; see `patches` and `next_id`.
    - `version_id` string, nullable, required: Null while the version is still being converged.
  - `pen` Pen, required
    - `access` 'Public' | 'Private' | 'Protected' | 'Collaborators', required: `Public`; `Private` (not listed on the site; anyone with the link can view it); `Protected` (private and password protected); `Collaborators` (private and for collaborators only). Anything but `Public` needs a PRO plan.
    - `build` Build
      - `applied_patches` BuildPatch[], required: Changes the API applied to the caller's files on the compiler's behalf.
        - `content` string, nullable, required: Set for `create` and `update`.
        - `file_id` string, nullable, required: Set for `update` and `delete`.
        - `path` string, required
        - `type` string, required: `create`, `update` or `delete`.
      - `diagnostics` BuildDiagnostic[], required: Every diagnostic of the final build.
        - `block_name` string, nullable, required
        - `code` string, nullable, required
        - `file_id` string, nullable, required
        - `message` string, required
        - `path` string, nullable, required
        - `range` FileRange, required
          - `end` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
          - `start` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
        - `scope` 'Build' | 'BuildStep' | 'File', required
        - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
        - `url` string, nullable, required
      - `ended_at` string, date-time, nullable, required
      - `errors` BuildDiagnostic[], required: The diagnostics with `type` `Error`.
        - `block_name` string, nullable, required
        - `code` string, nullable, required
        - `file_id` string, nullable, required
        - `message` string, required
        - `path` string, nullable, required
        - `range` FileRange, required
          - `end` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
          - `start` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
        - `scope` 'Build' | 'BuildStep' | 'File', required
        - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
        - `url` string, nullable, required
      - `files` File[]: The compiled output served under the version's `preview_url`. On the single version and build endpoints and the writes, and only when the build succeeded.
        - `bytes` integer, required
        - `content` string, nullable, required: Null for binary files, which are read from `url`.
        - `content_hash` string, required
        - `content_type` string, required: The media type the file is served with, from its extension.
        - `download_url` string, uri, nullable, required: The file's exact bytes for anyone holding the URL, on the API host (`GET /v2/pens/{id}/download/{path}`), for one hour from this response: no API key, session or Referer needed. Served as an attachment with the file's `content_type`. A new URL comes with every read; an expired one answers `403`. Null for the files of a Pen made in the classic editor.
        - `id` string, required: Stable across versions, renames and edits.
        - `is_binary` boolean, required
        - `name` string, required
        - `path` string, required
        - `url` string, uri, nullable, required: Where the file is served raw on the Pen's content domain. It follows the Pen's own access rules: a Private, Protected or Collaborators Pen needs a browser session and a Pen owned by a Free account needs a CodePen Referer, neither of which an API client has, so read files through `content` or `download_url`. Null for the files of a Pen made in the classic editor.
      - `id` string, required: The version's id, before and after the version is saved.
      - `next_id` string, nullable, required: The build applying this one's patches.
      - `patches` BuildPatch[], required: Changes the compiler still requires.
        - `content` string, nullable, required: Set for `create` and `update`.
        - `file_id` string, nullable, required: Set for `update` and `delete`.
        - `path` string, required
        - `type` string, required: `create`, `update` or `delete`.
      - `previous_id` string, nullable, required: The caller's build this one was converged from.
      - `rounds` integer, required: How many compiler builds it took, counted from the version the caller wrote.
      - `started_at` string, date-time, nullable, required
      - `status` 'Queued' | 'Running' | 'Success' | 'Failed' | 'Canceled', required: `Canceled` means changes are still required; see `patches` and `next_id`.
      - `version_id` string, nullable, required: Null while the version is still being converged.
    - `created_at` string, date-time, required
    - `deployment` Deployment, required
      - `created_at` string, date-time, required
      - `custom_domains` string[], required
      - `id` string, required
      - `updated_at` string, date-time, required
      - `url` string, uri, required
      - `version_id` string, required
    - `description` string, required
    - `editor` 'Classic' | 'V2', required: `V2`, or `Classic` for a Pen made in the classic editor, which is read-only through the API.
    - `id` string, required: The cpid, or the hashid for a Pen made in the classic editor.
    - `loves_count` integer, required
    - `password` string, nullable, required: Write-only, so always null.
    - `popularity` integer, required
    - `saved_version` Version, required
      - `build` Build, required
        - `applied_patches` BuildPatch[], required: Changes the API applied to the caller's files on the compiler's behalf.
          - `content` string, nullable, required: Set for `create` and `update`.
          - `file_id` string, nullable, required: Set for `update` and `delete`.
          - `path` string, required
          - `type` string, required: `create`, `update` or `delete`.
        - `diagnostics` BuildDiagnostic[], required: Every diagnostic of the final build.
          - `block_name` string, nullable, required
          - `code` string, nullable, required
          - `file_id` string, nullable, required
          - `message` string, required
          - `path` string, nullable, required
          - `range` FileRange, required
            - `end` FileLocation, required
              - …
            - `start` FileLocation, required
              - …
          - `scope` 'Build' | 'BuildStep' | 'File', required
          - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
          - `url` string, nullable, required
        - `ended_at` string, date-time, nullable, required
        - `errors` BuildDiagnostic[], required: The diagnostics with `type` `Error`.
          - `block_name` string, nullable, required
          - `code` string, nullable, required
          - `file_id` string, nullable, required
          - `message` string, required
          - `path` string, nullable, required
          - `range` FileRange, required
            - `end` FileLocation, required
              - …
            - `start` FileLocation, required
              - …
          - `scope` 'Build' | 'BuildStep' | 'File', required
          - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
          - `url` string, nullable, required
        - `files` File[]: The compiled output served under the version's `preview_url`. On the single version and build endpoints and the writes, and only when the build succeeded.
          - `bytes` integer, required
          - `content` string, nullable, required: Null for binary files, which are read from `url`.
          - `content_hash` string, required
          - `content_type` string, required: The media type the file is served with, from its extension.
          - `download_url` string, uri, nullable, required: The file's exact bytes for anyone holding the URL, on the API host (`GET /v2/pens/{id}/download/{path}`), for one hour from this response: no API key, session or Referer needed. Served as an attachment with the file's `content_type`. A new URL comes with every read; an expired one answers `403`. Null for the files of a Pen made in the classic editor.
          - `id` string, required: Stable across versions, renames and edits.
          - `is_binary` boolean, required
          - `name` string, required
          - `path` string, required
          - `url` string, uri, nullable, required: Where the file is served raw on the Pen's content domain. It follows the Pen's own access rules: a Private, Protected or Collaborators Pen needs a browser session and a Pen owned by a Free account needs a CodePen Referer, neither of which an API client has, so read files through `content` or `download_url`. Null for the files of a Pen made in the classic editor.
        - `id` string, required: The version's id, before and after the version is saved.
        - `next_id` string, nullable, required: The build applying this one's patches.
        - `patches` BuildPatch[], required: Changes the compiler still requires.
          - `content` string, nullable, required: Set for `create` and `update`.
          - `file_id` string, nullable, required: Set for `update` and `delete`.
          - `path` string, required
          - `type` string, required: `create`, `update` or `delete`.
        - `previous_id` string, nullable, required: The caller's build this one was converged from.
        - `rounds` integer, required: How many compiler builds it took, counted from the version the caller wrote.
        - `started_at` string, date-time, nullable, required
        - `status` 'Queued' | 'Running' | 'Success' | 'Failed' | 'Canceled', required: `Canceled` means changes are still required; see `patches` and `next_id`.
        - `version_id` string, nullable, required: Null while the version is still being converged.
      - `created_at` string, date-time, required
      - `deployed` boolean, required
      - `files` File[]: The version's source files; only on `GET /v2/versions/{id}` and the file writes.
        - `bytes` integer, required
        - `content` string, nullable, required: Null for binary files, which are read from `url`.
        - `content_hash` string, required
        - `content_type` string, required: The media type the file is served with, from its extension.
        - `download_url` string, uri, nullable, required: The file's exact bytes for anyone holding the URL, on the API host (`GET /v2/pens/{id}/download/{path}`), for one hour from this response: no API key, session or Referer needed. Served as an attachment with the file's `content_type`. A new URL comes with every read; an expired one answers `403`. Null for the files of a Pen made in the classic editor.
        - `id` string, required: Stable across versions, renames and edits.
        - `is_binary` boolean, required
        - `name` string, required
        - `path` string, required
        - `url` string, uri, nullable, required: Where the file is served raw on the Pen's content domain. It follows the Pen's own access rules: a Private, Protected or Collaborators Pen needs a browser session and a Pen owned by a Free account needs a CodePen Referer, neither of which an API client has, so read files through `content` or `download_url`. Null for the files of a Pen made in the classic editor.
      - `hash` string, required
      - `id` string, required
      - `label` string, nullable, required
      - `pen_id` string, required
      - `preview_url` string, uri, nullable, required: Null for a dry run's version, or when the key cannot read the Pen.
      - `saved` boolean, required: False only for a dry run's unsaved version.
    - `screenshot_urls` ScreenshotUrls, required: JPEG screenshots of the saved head, 16:9, by width. A screenshot is rendered the first time it is requested, so the first fetch can take a few seconds.
      - `large` string, uri, required: 800 pixels wide.
      - `medium` string, uri, required: 512 pixels wide.
      - `small` string, uri, required: 320 pixels wide.
      - `xlarge` string, uri, required: 1280 pixels wide.
    - `settings` Settings, required
      - `auto_deploy` boolean, required
      - `auto_run` boolean, required
      - `auto_save` boolean, required
      - `indent_with` string, required: `tabs` or `spaces`.
      - `tab_size` integer, required
    - `tags` string[], required
    - `template` boolean, required
    - `title` string, required
    - `updated_at` string, date-time, required
    - `urls` PenUrls, required
      - `editor` string, uri, required
      - `preview` string, uri, required: Renders the saved head on its own; 404s for Protected and Collaborators Pens, which need a browser session.
    - `views_count` integer, required: Views as the site shows them, tallied in batches, so it can trail by a few minutes.
  - `version` Version, required
    - `build` Build, required
      - `applied_patches` BuildPatch[], required: Changes the API applied to the caller's files on the compiler's behalf.
        - `content` string, nullable, required: Set for `create` and `update`.
        - `file_id` string, nullable, required: Set for `update` and `delete`.
        - `path` string, required
        - `type` string, required: `create`, `update` or `delete`.
      - `diagnostics` BuildDiagnostic[], required: Every diagnostic of the final build.
        - `block_name` string, nullable, required
        - `code` string, nullable, required
        - `file_id` string, nullable, required
        - `message` string, required
        - `path` string, nullable, required
        - `range` FileRange, required
          - `end` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
          - `start` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
        - `scope` 'Build' | 'BuildStep' | 'File', required
        - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
        - `url` string, nullable, required
      - `ended_at` string, date-time, nullable, required
      - `errors` BuildDiagnostic[], required: The diagnostics with `type` `Error`.
        - `block_name` string, nullable, required
        - `code` string, nullable, required
        - `file_id` string, nullable, required
        - `message` string, required
        - `path` string, nullable, required
        - `range` FileRange, required
          - `end` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
          - `start` FileLocation, required
            - `column` integer, required
            - `line` integer, required
            - `position` integer, nullable, required
        - `scope` 'Build' | 'BuildStep' | 'File', required
        - `type` 'Error' | 'Warning' | 'Information' | 'Hint' | 'Patch', required
        - `url` string, nullable, required
      - `files` File[]: The compiled output served under the version's `preview_url`. On the single version and build endpoints and the writes, and only when the build succeeded.
        - `bytes` integer, required
        - `content` string, nullable, required: Null for binary files, which are read from `url`.
        - `content_hash` string, required
        - `content_type` string, required: The media type the file is served with, from its extension.
        - `download_url` string, uri, nullable, required: The file's exact bytes for anyone holding the URL, on the API host (`GET /v2/pens/{id}/download/{path}`), for one hour from this response: no API key, session or Referer needed. Served as an attachment with the file's `content_type`. A new URL comes with every read; an expired one answers `403`. Null for the files of a Pen made in the classic editor.
        - `id` string, required: Stable across versions, renames and edits.
        - `is_binary` boolean, required
        - `name` string, required
        - `path` string, required
        - `url` string, uri, nullable, required: Where the file is served raw on the Pen's content domain. It follows the Pen's own access rules: a Private, Protected or Collaborators Pen needs a browser session and a Pen owned by a Free account needs a CodePen Referer, neither of which an API client has, so read files through `content` or `download_url`. Null for the files of a Pen made in the classic editor.
      - `id` string, required: The version's id, before and after the version is saved.
      - `next_id` string, nullable, required: The build applying this one's patches.
      - `patches` BuildPatch[], required: Changes the compiler still requires.
        - `content` string, nullable, required: Set for `create` and `update`.
        - `file_id` string, nullable, required: Set for `update` and `delete`.
        - `path` string, required
        - `type` string, required: `create`, `update` or `delete`.
      - `previous_id` string, nullable, required: The caller's build this one was converged from.
      - `rounds` integer, required: How many compiler builds it took, counted from the version the caller wrote.
      - `started_at` string, date-time, nullable, required
      - `status` 'Queued' | 'Running' | 'Success' | 'Failed' | 'Canceled', required: `Canceled` means changes are still required; see `patches` and `next_id`.
      - `version_id` string, nullable, required: Null while the version is still being converged.
    - `created_at` string, date-time, required
    - `deployed` boolean, required
    - `files` File[]: The version's source files; only on `GET /v2/versions/{id}` and the file writes.
      - `bytes` integer, required
      - `content` string, nullable, required: Null for binary files, which are read from `url`.
      - `content_hash` string, required
      - `content_type` string, required: The media type the file is served with, from its extension.
      - `download_url` string, uri, nullable, required: The file's exact bytes for anyone holding the URL, on the API host (`GET /v2/pens/{id}/download/{path}`), for one hour from this response: no API key, session or Referer needed. Served as an attachment with the file's `content_type`. A new URL comes with every read; an expired one answers `403`. Null for the files of a Pen made in the classic editor.
      - `id` string, required: Stable across versions, renames and edits.
      - `is_binary` boolean, required
      - `name` string, required
      - `path` string, required
      - `url` string, uri, nullable, required: Where the file is served raw on the Pen's content domain. It follows the Pen's own access rules: a Private, Protected or Collaborators Pen needs a browser session and a Pen owned by a Free account needs a CodePen Referer, neither of which an API client has, so read files through `content` or `download_url`. Null for the files of a Pen made in the classic editor.
    - `hash` string, required
    - `id` string, required
    - `label` string, nullable, required
    - `pen_id` string, required
    - `preview_url` string, uri, nullable, required: Null for a dry run's version, or when the key cannot read the Pen.
    - `saved` boolean, required: False only for a dry run's unsaved version.

## Other responses

- `400`: `BAD_USER_INPUT`: an invalid parameter, body, path, setting, access level or role. `field` names the argument when known, and `details` carries structured detail (the misses of `PATCH /v2/pens/{id}/files`).
- `401`: `UNAUTHENTICATED`: a missing or invalid key, a deleted owner, or a Team key for a Team that is not PRO.
- `403`: `FORBIDDEN`: a write to a Pen made in the classic editor, or a plan limit (non-Public access, a Private Collection, file size, storage, collaborators). The message names the limit and, when a bigger plan would lift it, where to upgrade.
- `404`: `NOT_FOUND`: no such item, or one that is not the key owner's, public or not. A path that is not an endpoint at all answers `404` with the v1 body `{ "error": "not found" }` instead.
- `409`: `CONFLICT`: `expected_version_id` is no longer the Pen's head. Read the Pen again and retry.
- `429`: `RATE_LIMITED`: the owner exceeded the plan's requests in an hour, its reads today, or today's allowance of Pen or Collection creates. No `Retry-After` or rate-limit headers are sent; the body carries `retry_after_seconds`, `limit` and `reset_at`.
- `500`: `INTERNAL`: unexpected, and reported; the message is generic.
- `504`: `BUILD_TIMEOUT`: a dry run's build did not finish inside `wait`, and there is no saved version to poll. Retry with a longer `wait`.

---

[API](https://skmtc.dev/codepen/apis/codepen-api.md) - [All operations](https://skmtc.dev/codepen/apis/codepen-api/llms.txt) - [OpenAPI document](https://skmtc.dev/codepen/apis/codepen-api/revisions/108fe91e3ef5?raw)
