Articles

Edit an article

Changes an article that already exists. Needs content: write, and is a write.

Absent and null are different. A property you leave out is left alone; a property you send as null is cleared. Send at least one property: an empty object answers 400.

content_markdown replaces the article's text in full. Send the whole article, not just the part that changed. It can't be null: an article always has text. It takes the same Markdown as Create an article (POST /newsletters/{newsletter}/articles), which documents it, and is parsed as strictly: text Commune cannot read answers 400 naming the line, and nothing is written.

This never moves the article's state. There is no status here, no posted_at, no scheduled_for. Queueing, cancelling, sending and retrying are their own operations. Neither is the byline: who is credited on an article cannot be changed here.

Which articles may be edited

A draft, a scheduled article, and one whose send failed. Everything else answers 422 with a message saying which case it is:

  • being sent right now: an edit mid send would reach part of the list and not the rest. Wait for it to finish.
  • sent: the email cannot be recalled, so an edit would change only the web page.
  • archived: unarchive it in Commune first.
  • imported: the body is a copy of what the newsletter's provider published and cannot be edited here.

Only a newsletter Commune publishes. Anything but a commune newsletter has its articles written elsewhere, and answers 422 with the code not_commune_newsletter, carrying a docs_url of https://usecommune.dev/errors/not_commune_newsletter.

Editing the body clears the HTML content returns until the article is next opened in Commune's editor. content_markdown is rendered from the article itself and is correct immediately.

Publishes no event. The article's updated_at is what says it changed.

patch/articles/{article}

Request

  • Base URL: https://api.usecommune.com
  • URL: https://api.usecommune.com/articles/{article}
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://usecommune.com/api/oauth/authorize, token URL https://usecommune.com/api/oauth/token, scopes: content:write)

Headers

Idempotency-Keystring required

A value of your choosing naming the change this request is making.

Send the same value again to retry the same request. Commune replays the answer the first attempt gave instead of making the change twice, and marks the replay with an Idempotent-Replay: true response header. Send a different value for a different change: a key reused for a request that differs in any way answers 409, because replaying an answer to a question you did not ask is a wrong answer you could not detect.

A UUID per change is the usual choice. Remembered for 24 hours, per credential, so two credentials choosing the same value never see each other's answers.

Required, not optional.

Request body

titlestring nullable

The subject line. Null clears it.

preview_textstring nullable

The short line email clients show after the subject. Null clears it.

image_urlstring uri nullable

The cover image. Null clears it.

slugstring

The article's URL segment. Changing it moves the article's permalink, and nothing forwards the old one, so change it knowing that.

It is not re-derived when you change the title. A slug that already belongs to another article of this newsletter answers 422.

content_markdownstring

An article's text, as Markdown. Create an article documents the Markdown Commune accepts.

Example request

{
  "title": "What we learned in March, revisited"
}

Response

The article, as it now stands. Without content: read it back with GET /articles/{article} when you want the stored body.

object'article' required

Always article.

idstring uuid required

Stable identifier.

short_idstring required

Eight character base62 identifier, unique across Commune. Safe in a URL and accepted anywhere {article} is.

slugstring required

URL segment under the newsletter, unique within it but not across Commune. The permalink is /n/{handle}/a/{slug}. Falls back to the short_id for an untitled article.

titlestring nullable

Subject line of the article. Null for an untitled draft.

preview_textstring nullable

The short line email clients show after the subject, and what Commune uses as the excerpt on a card.

image_urlstring uri nullable

Cover image. When the creator set none, Commune stamps the first image in the body at send time, so this is usually populated for a sent article.

external_urlstring uri nullable

The article's canonical URL on the newsletter's own provider, for an imported article. Null for one written in Commune.

status'draft' | 'scheduled' | 'sending' | 'sent' | 'failed' | 'archived' required

Where an article is in its life. A credential holding only read permissions ever sees sent and nothing else. An imported article is always sent, since Commune sees it after the provider delivered it.

is_importedboolean required

true when the article came in from the newsletter's provider, false when it was written and sent in Commune.

posted_atstring date-time nullable

When the article went out. An article dated in the future is not returned by any read operation until that moment passes, so this is never ahead of now in a response.

scheduled_forstring date-time nullable

When a queued article may go out. Set while status is scheduled and null otherwise.

This is not posted_at and the difference matters: a queued article has no publication date yet, which is why it stays invisible on every reader surface until it really goes out. Commune dispatches in passes, so this is the moment from which the article may go rather than the moment it will.

created_atstring date-time required

When the row was created in Commune.

updated_atstring date-time

When the article was last edited.

Example response

{
  "short_id": "k7Rm2xQp",
  "newsletter": {
    "object": "newsletter",
    "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
  },
  "authors": [
    {
      "object": "newsletter",
      "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
    }
  ],
  "thread": {
    "object": "newsletter",
    "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.