---
title: "Edit a piece of content"
method: PATCH
path: "/v1/content/{contentId}"
tags: ["content"]
---

# Edit a piece of content

`PATCH /v1/content/{contentId}`

Rename a piece of content, replace its body, or both.

**Replacement, not a merge:** `body` replaces the artifact entirely, in the same shape the kind takes on create. Send the whole thing, not just the part that changed. Media already attached to the draft is the one exception — you can't send it back, so it's carried over rather than dropped.

**Scheduled pieces are locked:** if a send is queued or already running for this piece, its words go out exactly as written, so an edit to `body` is refused with an explanation. Cancel the schedule in the app first. Renaming is always allowed — a title isn't published anywhere.

## Path parameters

- `contentId` string, required

## Request body

- object
  - `title` string — New name for this piece in your library
  - `body` object — The replacement artifact, in the shape this piece's kind uses
    - `text` string — The post's text. `tweet`: a single tweet, at most 280 characters — use `tweets` for a thread and never send both. `linkedin`: the post body.
    - `tweets` string[] — `tweet` only. One entry per tweet, in posting order, each at most 280 characters. Never concatenate a thread into one entry.
    - `subject` string — `newsletter` only. Subject line.
    - `preheader` string — `newsletter` only. Optional preview line shown after the subject.
    - `body` string — `newsletter`: the email body. `x_article`: the article's full CommonMark markdown.
    - `title` string — `x_article` only. The headline as published on X. Separate from the piece's `title`, which only names it in your library.
    - `canonicalUrl` string — `x_article` only. The original post this Article is a version of. It must also appear as a markdown link inside `body`.
    - `media` unknown

## Response `200`

Content updated successfully

- object
  - `id` string, required — Unique identifier for this piece of content
  - `kind` string, required — What this piece is: `tweet`, `linkedin`, `newsletter`, or `x_article`
  - `title` string, required — What this piece is called in your library
  - `excerpt` string, required — First readable line of the body, for listing views
  - `status` 'draft' | 'published' | 'archived', required — Whether this piece has been delivered, is still a draft, or was archived
  - `scheduled` boolean, required — Whether a scheduled send is queued against this piece
  - `lockedReason` string, nullable, required — Why this piece can't be edited right now, or null when it can. A queued or in-flight send locks the words, because they go out exactly as written.
  - `publishedAt` string, nullable, required — ISO 8601 timestamp of the first delivery, or null
  - `url` string, nullable, required — Where this piece went live, from the same delivery `publishedAt` came from. Null when it hasn't been delivered, and null by design for a channel that publishes no page: a custom email renders into the message itself, so there is no address to link to. Never guessed — a delivery whose id isn't shaped like its channel reports null rather than a link that would 404.
  - `archivedAt` string, nullable, required — ISO 8601 timestamp of when this piece was archived, or null
  - `createdAt` string, required — ISO 8601 timestamp of creation
  - `updatedAt` string, required — ISO 8601 timestamp of the last change
  - `body` object, required — The artifact itself, in the shape its kind uses

## Other responses

- `400` — The draft doesn't match its kind, or a queued send has locked it
- `401` — Invalid or missing API key
- `404` — Content not found
- `500` — Internal server error

---

[API](https://skmtc.net/paragraph-xyz/apis/paragraph-api.md) · [All operations](https://skmtc.net/paragraph-xyz/apis/paragraph-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/paragraph-xyz/paragraph-api/revisions/d7ee6288035e/schema)
