Articles

Retrieve an article

Read one article, including its content. This is the only operation that returns a body.

The same two gates apply as on the list. An article stamped with an audience answers 404 to a credential that does not hold that audience, and a future dated article answers 404 until it goes live, including to the newsletter's own team, so that a preview link cannot be shared early.

For an article written in Commune, content is the email rendered to HTML with personalization placeholders resolved against an empty context, so a merge tag never leaks as raw text. For an imported article it is the body as it arrived from the provider.

?expand=content adds content_markdown, the same body as Markdown. Ask for it when a model is going to read the article, and ask for ?fields=content_markdown with it to leave the HTML behind entirely.

get/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:read)

Query parameters

expandstring

Comma-separated list of relationship paths to inline in the response. Unexpanded relationships are returned as a reference object carrying only id and object. Each operation documents the paths it accepts, and an unknown path answers 400. Nested paths use a dot, for example article.newsletter.

fieldsstring

Comma-separated allow-list of top level properties to return on each object, so a client can trim a response it does not need in full. id and object are always returned. An unknown property name answers 400. Properties omitted by an operation, such as content on any article list, cannot be brought back with fields.

Response

The article, with content.

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.

contentstring required

The body as HTML. For an article written in Commune this is the email rendered for the web, with personalization placeholders resolved against an empty context so no raw merge tag is ever served. For an imported article it is what the provider published.

Treat it as untrusted markup from a third party and render it in a sandboxed context.

content_markdownstring nullable

The same body as Markdown, present only when content is named in ?expand=. It is what a model should read: the HTML is mostly markup it will not use, and one article body can fill a context window on its own.

It is a conversion of the body rather than of the HTML above. For an article written in Commune it comes from the document the author wrote, so a code block keeps its language and a table that declares a header becomes a Markdown table. For an imported article it comes from the provider's HTML. Either way the words, the links, the images, the lists, the code and the quotes survive, and everything presentational does not.

null means Commune holds no body it can convert faithfully. That happens when the only body it stored is a rendered email, whose words cannot be told apart from its layout. An empty string means the article has no body, which is different.

No merge tag ever appears here, resolved or not.

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.