---
title: "Write a content key to the draft"
method: PUT
path: "/api/v1/sites/{slug}/content/{key}"
tags: ["Content"]
---

# Write a content key to the draft

`PUT /api/v1/sites/{slug}/content/{key}`

## Request

- Base URL: `https://api.dotsy.ai`
- URL: `https://api.dotsy.ai/api/v1/sites/{slug}/content/{key}`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

Stages one key (a page, layout, fragment or data file). A layout's key is `layouts/<name>.html` and a fragment's is `fragments/<name>.html`; a `<dotsy-fragment name>` tag and a route's `layout` use the bare name. Nothing is live until you publish. The answer is 201 when the key is new and 200 when it replaced an existing one. Writing the same body again changes nothing.

Send `{ body, contentType? }`. With `?format=post`, send a blog post document `{ meta, body, head?, slug? }` instead; the server builds the page from it. Keys under `.dotsy/`, `.structure/`, `_intent/` and `_data/` are reserved (400 `reserved_key`). For a body over about 60 KB, use `PUT …/content-raw/{key}` or a changeset with staged chunks.

## Path parameters

- `slug` string, required
- `key` string, required

## Query parameters

- `format` 'post'

## Headers

- `If-Match` string

## Request body

- union
  - PutContentRequest
    - `body` string, required: The whole file as text (up to 5,000,000 characters). An HTML page needs some non-whitespace text.
    - `contentType` string: Stored Content-Type. Defaults from the key's extension (`.html` becomes `text/html`).
  - PutPostRequest
    - `meta` object, required
      - `title` string, required: Post title — shown on the blog card/listing and used as the <title> unless seoTitle overrides it.
      - `seoTitle` string: SEO override for the <title>/og:title tags only. The blog card and listing always show `title`; empty or absent inherits `title`.
      - `date` string
      - `dateDisplay` string
      - `excerpt` string
      - `tags` string[]
      - `author` string
      - `image` string
      - `url` string
      - `visibleAt` string
      - `collections` string[]
      - `custom` object
    - `body` string, required: The post body HTML.
    - `head` string[]: Extra `<head>` tags to keep on the post.
    - `slug` string: File name without extension. Defaults to the key's last segment.

## Response `200`

Replaced an existing key.

- PutContentResponse
  - `key` string, required: The content key.
  - `contentType` string, required
  - `contentHash` string, required: SHA-256 of the effective body: the staged draft if there is one, else the live version. Send it back as `If-Match` on a write to refuse the write if someone else changed the key meanwhile.
  - `updatedAt` number, required: Write time, Unix ms.
  - `created` boolean, required: True when the key did not exist before this write (the status is then 201).
  - `warnings` string[]: Non-blocking notes about the content: tags that will not compose (`<key>: <code> — <what to change>`; codes `fragment_unclosed`, `fragment_bad_name`, `fragment_full_document`, `fragment_self_reference`, `fragment_attr_hyphen`, `legacy_paige_tag`, `layout_missing_content`, `unknown_dotsy_syntax`) or post fields that were not saved. The write still happened.
  - `published` false, required: Always false: the change is staged in the draft until you publish.
  - `hint` string, required: Reminder that the change is staged and how to make it live.

## Other responses

- `201`: Created a new key.
- `400`: `invalid_key`, `reserved_key`, `invalid_body` (with `issues`), `invalid_post` (with `field`), or `empty_page_body` (an HTML page needs some text).
- `401`: Missing or invalid credentials.
- `403`: The key or token cannot write to this site, or a plan limit blocks the write (`page_limit_reached`, `signature_required_on_free`).
- `404`: No such site (`site_not_found`).
- `409`: `conflict`: `If-Match` no longer matches. Or `placement_version_conflict`: the site's storage changed; retry.
- `413`: The plan's storage limit is reached (`storage_limit_reached`).

---

[API](https://skmtc.dev/dotsy/apis/dotsy-api.md) · [All operations](https://skmtc.dev/dotsy/apis/dotsy-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dotsy/apis/dotsy-api/revisions/4272ed3b85d7?raw)
