Show more

Use to navigate results, ENTER to select one, ESC to close

Type in any word to easily find the endpoint, property or group of operations you are looking for.

API Explorer API changelog
Download source
  • JSON OpenAPI specification
  • YAML OpenAPI specification
Guides
REST API logo

Topics

  • Introduction
  • Authentication

Newsletters and people

  • Newsletters
    • List newsletters GET
    • Retrieve a newsletter GET
  • Team
    • List a newsletter's team GET
    • List this account's memberships GET
  • Users
    • Retrieve the authenticated account GET
    • Retrieve a user GET
  • Search
    • Search your newsletters GET

Publishing

  • Articles
    • List a newsletter's articles GET
    • Create an article POST
    • Retrieve an article GET
    • Edit an article PATCH
    • List an article's authors GET
    • Store an image for an article POST
    • Send a test copy of an article POST
    • Schedule an article POST
    • Cancel a scheduled article POST
    • Send an article to the list POST
    • List the articles this account saved GET
    • List the articles this account liked GET
  • Highlights
    • List an article's highlights GET
    • Retrieve a highlight GET

Community

  • Threads
    • List a newsletter's threads GET
    • Start a thread POST
    • Retrieve a thread GET
    • Set who a conversation is private to PATCH
    • Put a thread on the global feed POST
    • Reply in a thread POST
  • Messages
    • List a thread's messages GET
    • Retrieve a message GET
  • Chat rooms
    • List a newsletter's chat rooms GET
    • Retrieve a chat room GET

Audience

  • Subscribers
    • List a newsletter's subscribers GET
    • Add a subscriber POST
    • Retrieve a subscriber GET
    • Erase a subscriber DELETE
    • Update a subscriber PATCH
    • List the newsletters this account subscribes to GET
    • List a newsletter's community GET
  • Subscriber tags
    • List a newsletter's tags GET
    • Create a tag POST
    • Retrieve a tag GET
    • Delete a tag DELETE
    • Rename a tag PATCH
    • Apply a tag to many subscribers POST
    • Apply a tag to a subscriber POST
    • Take a tag off a subscriber DELETE

Insights

  • Engagement
    • List a newsletter's subscriber insights GET
    • List a newsletter's engagement events GET
  • Metrics
    • Retrieve a newsletter's headline numbers GET
    • Retrieve a newsletter's acquisition breakdown GET
    • Retrieve one newsletter metric bucketed over time GET
    • Retrieve one article's performance GET

Sending and domains

  • Sends
    • List a newsletter's sends GET
    • Retrieve a send GET
  • Senders
    • List a newsletter's sending addresses GET
    • Retrieve a sending address GET
  • Website domains
    • List a newsletter's website domains GET
    • Retrieve a website domain GET
    • Change what a website domain serves PATCH
  • Automations
    • List a newsletter's automations GET
    • Create an automation POST
    • List the events an automation can trigger on GET
    • Retrieve an automation GET
    • Archive an automation DELETE
    • Update an automation PATCH
    • Turn an automation on POST
    • Turn an automation off POST
    • List an automation's runs GET
    • Send a test copy of one step's email POST
    • Retrieve an automation run GET

Creator websites

  • Creator websites
    • List a newsletter's website pages GET
    • Create a website page POST
    • Retrieve a website page GET
    • Delete a website page DELETE
    • Change a website page PATCH
    • Publish a website page POST
    • Unpublish a website page POST
    • Store a website asset POST
    • List a newsletter's publishable keys GET
    • Create a publishable key POST
    • Revoke a publishable key DELETE
    • Rotate a publishable key POST

Platform

  • Platform
    • Service status GET
    • Retrieve the calling credential's rate limit state GET
    • What this credential may call GET
    • List this newsletter's API keys GET
    • Retrieve an API key GET
    • Revoke an API key DELETE
  • Event delivery
    • List where a newsletter's events go GET
    • List what was delivered where, and how it went GET
    • Retrieve one delivery attempt GET
    • Send an event to a destination again POST
    • Open the event delivery portal POST
  • Webhooks
    • Article like added or removed POST
    • Article published POST
    • Article read POST
    • Article scheduled POST
    • Automation run completed POST
    • Automation run ended early POST
    • Automation run started POST
    • Billing subscription state changed POST
    • Delivery bounced POST
    • Delivery link clicked POST
    • Delivery marked as spam POST
    • Delivery accepted by the recipient server POST
    • Delivery opened POST
    • Custom website domain verified POST
    • Highlight created POST
    • Import finished POST
    • Message created POST
    • Send completed POST
    • Send failed POST
    • Sender verified POST
    • Subscriber created POST
    • Subscriber insight status changed POST
    • Subscriber tag added or removed POST
    • Subscriber unsubscribed POST
    • Thread created POST
    • Thread published to the feed POST
Powered by Bump.sh
API Explorer API changelog
Download source
  • JSON OpenAPI specification
  • YAML OpenAPI specification
Guides
REST API logo

Search your newsletters Run in API Explorer

Ask AI
  • Add to Cursor
  • Add to VSCode
  • Add to other AI tools (MCP)

  • Open in ChatGPT
  • Open in Claude

  • View as Markdown
  • Copy as Markdown

Add MCP server to your AI tool

Allow AI tools and LLMs to interact with the API documentation portal through MCP.

MCP server URL

https://api-reference.usecommune.dev/mcp

Standard setup for AI tools providing an mcp.json file

mcp.json
{
  "REST API MCP server": {
    "url": "https://api-reference.usecommune.dev/mcp"
  }
}

Close
GET /search
Api key Oauth2

Full text search across the newsletters this credential was granted: the newsletters themselves, their articles and their chat, ranked by relevance. Nothing outside those newsletters is searched.

Results obey the same gates as the resource operations do, evaluated at the public audience. An article stamped with an audience, an article dated in the future, a draft, and a thread that is not public are never returned, so search cannot be used to see around a permission.

Search returns public content only, whatever the credential is. Everything in a result is something a logged out visitor could already read on the web. That is deliberately narrower than what a credential can reach directly: a key granted content:read on its own newsletter still does not find that newsletter's audience-stamped issues or its private rooms here. Read those through the article and thread operations, which evaluate the audience against the credential. Searching your own restricted content is not part of this operation.

A query shorter than two characters returns an empty page rather than an error, so a caller can send it on every keystroke.

Headers

  • Commune-Version string

    The contract version this request is written against. Every version published so far is a release date (YYYY-MM-DD), which is why the examples look like one, but the value is an opaque identifier: match it against the versions this API publishes rather than parsing it, because a future one may not be only a date. An unknown value answers 400 with invalid_version.

    Omitting the header pins the request to the version that was current when the API key was issued, so an integration keeps working when a newer version ships.

    Minimum length is 1.

Query parameters

  • q string Required

    The query. Shorter than two characters returns an empty page.

    Maximum length is 200.

  • type string

    Return only results of this kind. Repeat the parameter to accept several. Omit for all kinds.

    Values are newsletter, article, thread, or message.

  • cursor string

    The pagination.next_cursor value from the previous page. Omit it to read the first page. A cursor is opaque, is only valid for the same operation with the same filters, and is not a durable identifier.

    Maximum length is 512.

  • limit integer

    How many items to return in this page. This is a page size, not an offset. Fewer items than requested may come back and that does not mean the collection is exhausted, only an absent next_cursor does.

    Minimum value is 1, maximum value is 100. Default value is 20.

  • expand string

    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.

  • fields string

    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.

Responses

  • 200 application/json

    A page of results, most relevant first.

    Hide response attributes Show response attributes object
    • object string Required

      Always list, so a response is self describing.

      Value is list.

    • pagination object Required

      Cursor pagination state. Commune never exposes an offset or a page number: a collection is a moving window, and an offset silently skips or repeats items when the window shifts between two requests.

      Additional properties are NOT allowed.

      Hide pagination attributes Show pagination attributes object
      • has_more boolean Required

        Whether another page exists. When false, next_cursor is null.

      • next_cursor string | null Required

        Pass this back as ?cursor= to read the next page. null on the last page. Opaque, and valid only for the same operation with the same filters.

    • data array[object]

      This page of hits, most relevant first by score. Scores are comparable within one response and not across responses or contract versions. A hit the credential could not read directly is absent rather than redacted, so a page can be shorter than the number of matches Commune holds and search cannot be used to see around a permission. A query shorter than two characters returns an empty page rather than an error.

      Hide data attributes Show data attributes object

      One hit. It always carries enough to render a row without a second request, and points at the full resource through resource.

      • object string Required

        Always search_result.

        Value is search_result.

      • type string Required

        What a search result points at. There is no post or comment kind: a discussion result is a thread or a message.

        Values are newsletter, article, thread, or message.

      • title string | null

        The heading for the row: a newsletter's name, an article's title, a person's display name. Null for a chat hit, which has no title.

      • snippet string | null

        A fragment of the matching text with the query terms in it, as plain text. Null when the match was on the title alone.

      • url string(uri)

        Where the hit lives on the web.

      • score number

        How well the hit matched, higher being better. Results come back ordered by it, so use it to compare hits within one response and to draw a relevance cutoff. It is not comparable across queries or across contract versions, and the scale is undefined.

        Minimum value is 0.

      • resource object | null Required

        The object itself. A Ref unless resource is named in ?expand=, in which case it is the full object of the kind named by type.

        Any of:
        Ref object | null Newsletter object Article object | null Thread object | null Message object

        An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

        Hide attributes Show attributes
        • object string Required

          The type of the referenced resource.

        • id string Required

          The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

        A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

        Hide attributes Show attributes
        • object string Required

          Always newsletter.

          Value is newsletter.

        • id string(uuid) Required

          Stable identifier.

        • handle string Required

          The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

        • name string Required

          Display name, as the creator writes it.

        • description string | null

          The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

        • esp string Required

          Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

          Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

        • image_url string(uri) | null

          Square avatar for the newsletter.

        • website_url string(uri) | null

          The creator's own site, if they linked one.

        • social_links object

          The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

          Additional properties are NOT allowed.

          Hide social_links attributes Show social_links attributes object
          • twitter string(uri)

            X or Twitter profile URL.

          • bluesky string(uri)

            Bluesky profile URL.

          • linkedin string(uri)

            LinkedIn profile URL.

          • mastodon string(uri)

            Mastodon profile URL, including the instance host.

          • youtube string(uri)

            YouTube channel URL.

          • instagram string(uri)

            Instagram profile URL.

          • threads string(uri)

            Threads profile URL.

          • github string(uri)

            GitHub profile URL.

        • language string | null

          Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

        • chat_create_permission string

          Who may start a new chat thread in this community.

          Values are editors, subscribers, or anyone.

        • allow_non_subscriber_chat boolean

          Whether people who have not subscribed may reply in existing threads.

        • owner object | null

          The account that owns the newsletter. A Ref unless owner is named in ?expand=.

          Any of:
          Ref object | null User object

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

          Hide attributes Show attributes
          • object string Required

            Always user.

            Value is user.

          • id string Required

            Stable identifier.

          • username string | null

            The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

          • display_name string | null

            The name shown next to their messages and bylines.

          • avatar string(uri) | null

            Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

        • featured_article object | null

          The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

          One of:
          Ref object | null Article object | null

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

          Hide attributes Show attributes
          • object string Required

            Always article.

            Value is article.

          • id string(uuid) Required

            Stable identifier.

          • short_id string Required

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

          • slug string 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.

          • newsletter object | null Required

            The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

            One of:
            Ref object | null Newsletter object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

            Additional properties are NOT allowed.

          • title string | null

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

          • preview_text string | null

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

          • image_url string(uri) | null

            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_url string(uri) | null

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

          • status string 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.

            Values are draft, scheduled, sending, sent, failed, or archived.

          • is_imported boolean Required

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

          • posted_at string(date-time) | null

            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_for string(date-time) | null

            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.

          • authors array[object]

            The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

            Any of:
            Ref object | null User object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

            Hide attributes Show attributes
            • object string Required

              Always user.

              Value is user.

            • id string Required

              Stable identifier.

            • username string | null

              The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

            • display_name string | null

              The name shown next to their messages and bylines.

            • avatar string(uri) | null

              Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

          • thread object | null

            The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

            One of:
            Ref object | null Thread object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

            Hide attributes Show attributes
            • object string Required

              Always thread.

              Value is thread.

            • id string(uuid) Required

              Stable identifier.

            • short_id string | null

              Eight character base62 identifier used by the thread's own URL at /n/{handle}/chat/{short_id}. Null for a thread Commune opened under an article, which is reached through the article instead.

            • newsletter object | null Required

              The community this thread lives in. A Ref unless newsletter is named in ?expand=.

              One of:
              Ref object | null Newsletter object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

              Additional properties are NOT allowed.

            • author object | null

              Who opened the thread. A Ref unless author is named in ?expand=.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • content string Required

              The opening message. HTML, since people format what they write. Treat it as untrusted markup and render it in a sandboxed context.

            • media array[object]

              Attachments on the opening message.

              Hide media attributes Show media attributes object

              An image or file attached to a thread or a message.

              • url string(uri) Required

                Where the attachment is served from.

              • type string | null

                The attachment's media type when Commune recorded one, for example image/png. Null for an attachment old enough that none was recorded.

              • thumbnail string(uri) | null

                A smaller rendition, when one was generated.

            • visibility string Required

              Where a thread is placed. public puts it on the global Commune feed and makes it readable by anyone. subscribers keeps it inside the newsletter. Set and changed by the newsletter's team.

              A third value, paid, was in this enum until 2026-10-10. It was never produced by anything and no thread ever carried it, so it was removed rather than left as a state consumers had to handle. See Removals under Versioning.

              Values are public or subscribers.

            • audience_scoped boolean Required

              true when this thread is a private room: it was scoped to one or more of the newsletter's subscriber segments, and only the people holding one of those segments and the newsletter's team can read it or its replies. Evaluated live, so losing the segment takes the conversation away on the next request.

              A private thread is never on the global feed, so visibility is subscribers whenever this is true. Scoping a public thread to a room moves it to subscribers in the same write.

              Always present. It says that the conversation is private without saying to whom, which is why every credential that can read the thread gets it while audience_tag_ids is narrower.

            • audience_tag_ids array[string(uuid)] | null

              Which segments the thread is private to, by tag id, or null when it is not private. The semantics are OR: holding any one of them is enough.

              Present only for a credential holding audience: read on this newsletter. A thread is content, and the words in it come back to any credential the thread's own gate admits; which segments it was addressed to is the audience family's fact, priced at audience: read everywhere else a credential can ask for it (GET /newsletters/{newsletter}/tags, GET /tags/{tag}). So a credential without that family sees audience_scoped and not this property, and cannot read a creator's segmentation off a conversation. Absent and null are different answers: absent is "this credential may not read it", null is "there is none".

              Every id here is a tag with is_room set, because that is the only kind a thread can be scoped to. A tag that was since retired or un-roomed stays in the list and goes on deciding who may read the thread, exactly as it goes on deciding the audience of an article it was addressed to.

            • is_article_thread boolean Required

              true when Commune opened this thread under an article rather than a person starting it. These are kept off the global feed, because the article card already represents the conversation there.

            • article object | null

              The article that opened this thread, when is_article_thread is true. null otherwise. A Ref unless article is named in ?expand=.

              One of:
              Ref object | null Article object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

            • reply_count integer

              Undeleted replies in the thread, at any depth.

              Minimum value is 0.

            • view_count integer

              How many times the thread was opened.

              Minimum value is 0.

            • created_at string(date-time) Required

              When the thread was opened.

            • updated_at string(date-time)

              When the thread row last changed for any reason.

            • edited_at string(date-time) | null

              When the author last edited the opening message. Null when it was never edited, which is what drives the edited marker in the product.

            • last_activity_at string(date-time) Required

              When the thread last received a reply, or when it was opened if it never did. This is the sort key for the thread list.

          • stats object

            Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

            Additional properties are NOT allowed.

            Hide stats attributes Show stats attributes object
            • likes integer Required

              How many people liked the article.

              Minimum value is 0.

            • comments integer Required

              Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

              Minimum value is 0.

            • highlights integer Required

              How many passages readers highlighted.

              Minimum value is 0.

          • created_at string(date-time) Required

            When the row was created in Commune.

          • updated_at string(date-time)

            When the article was last edited.

        • created_at string(date-time) Required

          When the newsletter was connected to or created on Commune.

        • updated_at string(date-time)

          When the profile last changed.

        One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

        Hide attributes Show attributes
        • object string Required

          Always article.

          Value is article.

        • id string(uuid) Required

          Stable identifier.

        • short_id string Required

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

        • slug string 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.

        • newsletter object | null Required

          The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

          One of:
          Ref object | null Newsletter object

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

          Hide attributes Show attributes
          • object string Required

            Always newsletter.

            Value is newsletter.

          • id string(uuid) Required

            Stable identifier.

          • handle string Required

            The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

          • name string Required

            Display name, as the creator writes it.

          • description string | null

            The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

          • esp string Required

            Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

            Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

          • image_url string(uri) | null

            Square avatar for the newsletter.

          • website_url string(uri) | null

            The creator's own site, if they linked one.

          • social_links object

            The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

            Additional properties are NOT allowed.

            Hide social_links attributes Show social_links attributes object
            • twitter string(uri)

              X or Twitter profile URL.

            • bluesky string(uri)

              Bluesky profile URL.

            • linkedin string(uri)

              LinkedIn profile URL.

            • mastodon string(uri)

              Mastodon profile URL, including the instance host.

            • youtube string(uri)

              YouTube channel URL.

            • instagram string(uri)

              Instagram profile URL.

            • threads string(uri)

              Threads profile URL.

            • github string(uri)

              GitHub profile URL.

          • language string | null

            Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

          • chat_create_permission string

            Who may start a new chat thread in this community.

            Values are editors, subscribers, or anyone.

          • allow_non_subscriber_chat boolean

            Whether people who have not subscribed may reply in existing threads.

          • owner object | null

            The account that owns the newsletter. A Ref unless owner is named in ?expand=.

            Any of:
            Ref object | null User object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

            Hide attributes Show attributes
            • object string Required

              Always user.

              Value is user.

            • id string Required

              Stable identifier.

            • username string | null

              The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

            • display_name string | null

              The name shown next to their messages and bylines.

            • avatar string(uri) | null

              Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

          • featured_article object | null

            The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

            One of:
            Ref object | null Article object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

          • created_at string(date-time) Required

            When the newsletter was connected to or created on Commune.

          • updated_at string(date-time)

            When the profile last changed.

        • title string | null

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

        • preview_text string | null

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

        • image_url string(uri) | null

          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_url string(uri) | null

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

        • status string 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.

          Values are draft, scheduled, sending, sent, failed, or archived.

        • is_imported boolean Required

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

        • posted_at string(date-time) | null

          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_for string(date-time) | null

          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.

        • authors array[object]

          The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

          Any of:
          Ref object | null User object

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

          Hide attributes Show attributes
          • object string Required

            Always user.

            Value is user.

          • id string Required

            Stable identifier.

          • username string | null

            The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

          • display_name string | null

            The name shown next to their messages and bylines.

          • avatar string(uri) | null

            Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

        • thread object | null

          The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

          One of:
          Ref object | null Thread object | null

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

          Hide attributes Show attributes
          • object string Required

            Always thread.

            Value is thread.

          • id string(uuid) Required

            Stable identifier.

          • short_id string | null

            Eight character base62 identifier used by the thread's own URL at /n/{handle}/chat/{short_id}. Null for a thread Commune opened under an article, which is reached through the article instead.

          • newsletter object | null Required

            The community this thread lives in. A Ref unless newsletter is named in ?expand=.

            One of:
            Ref object | null Newsletter object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

            Hide attributes Show attributes
            • object string Required

              Always newsletter.

              Value is newsletter.

            • id string(uuid) Required

              Stable identifier.

            • handle string Required

              The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

            • name string Required

              Display name, as the creator writes it.

            • description string | null

              The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

            • esp string Required

              Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

              Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

            • image_url string(uri) | null

              Square avatar for the newsletter.

            • website_url string(uri) | null

              The creator's own site, if they linked one.

            • social_links object

              The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

              Additional properties are NOT allowed.

              Hide social_links attributes Show social_links attributes object
              • twitter string(uri)

                X or Twitter profile URL.

              • bluesky string(uri)

                Bluesky profile URL.

              • linkedin string(uri)

                LinkedIn profile URL.

              • mastodon string(uri)

                Mastodon profile URL, including the instance host.

              • youtube string(uri)

                YouTube channel URL.

              • instagram string(uri)

                Instagram profile URL.

              • threads string(uri)

                Threads profile URL.

              • github string(uri)

                GitHub profile URL.

            • language string | null

              Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

            • chat_create_permission string

              Who may start a new chat thread in this community.

              Values are editors, subscribers, or anyone.

            • allow_non_subscriber_chat boolean

              Whether people who have not subscribed may reply in existing threads.

            • owner object | null

              The account that owns the newsletter. A Ref unless owner is named in ?expand=.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • featured_article object | null

              The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

              One of:
              Ref object | null Article object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

            • created_at string(date-time) Required

              When the newsletter was connected to or created on Commune.

            • updated_at string(date-time)

              When the profile last changed.

          • author object | null

            Who opened the thread. A Ref unless author is named in ?expand=.

            Any of:
            Ref object | null User object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

            Hide attributes Show attributes
            • object string Required

              Always user.

              Value is user.

            • id string Required

              Stable identifier.

            • username string | null

              The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

            • display_name string | null

              The name shown next to their messages and bylines.

            • avatar string(uri) | null

              Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

          • content string Required

            The opening message. HTML, since people format what they write. Treat it as untrusted markup and render it in a sandboxed context.

          • media array[object]

            Attachments on the opening message.

            Hide media attributes Show media attributes object

            An image or file attached to a thread or a message.

            • url string(uri) Required

              Where the attachment is served from.

            • type string | null

              The attachment's media type when Commune recorded one, for example image/png. Null for an attachment old enough that none was recorded.

            • thumbnail string(uri) | null

              A smaller rendition, when one was generated.

          • visibility string Required

            Where a thread is placed. public puts it on the global Commune feed and makes it readable by anyone. subscribers keeps it inside the newsletter. Set and changed by the newsletter's team.

            A third value, paid, was in this enum until 2026-10-10. It was never produced by anything and no thread ever carried it, so it was removed rather than left as a state consumers had to handle. See Removals under Versioning.

            Values are public or subscribers.

          • audience_scoped boolean Required

            true when this thread is a private room: it was scoped to one or more of the newsletter's subscriber segments, and only the people holding one of those segments and the newsletter's team can read it or its replies. Evaluated live, so losing the segment takes the conversation away on the next request.

            A private thread is never on the global feed, so visibility is subscribers whenever this is true. Scoping a public thread to a room moves it to subscribers in the same write.

            Always present. It says that the conversation is private without saying to whom, which is why every credential that can read the thread gets it while audience_tag_ids is narrower.

          • audience_tag_ids array[string(uuid)] | null

            Which segments the thread is private to, by tag id, or null when it is not private. The semantics are OR: holding any one of them is enough.

            Present only for a credential holding audience: read on this newsletter. A thread is content, and the words in it come back to any credential the thread's own gate admits; which segments it was addressed to is the audience family's fact, priced at audience: read everywhere else a credential can ask for it (GET /newsletters/{newsletter}/tags, GET /tags/{tag}). So a credential without that family sees audience_scoped and not this property, and cannot read a creator's segmentation off a conversation. Absent and null are different answers: absent is "this credential may not read it", null is "there is none".

            Every id here is a tag with is_room set, because that is the only kind a thread can be scoped to. A tag that was since retired or un-roomed stays in the list and goes on deciding who may read the thread, exactly as it goes on deciding the audience of an article it was addressed to.

          • is_article_thread boolean Required

            true when Commune opened this thread under an article rather than a person starting it. These are kept off the global feed, because the article card already represents the conversation there.

          • article object | null

            The article that opened this thread, when is_article_thread is true. null otherwise. A Ref unless article is named in ?expand=.

            One of:
            Ref object | null Article object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

          • reply_count integer

            Undeleted replies in the thread, at any depth.

            Minimum value is 0.

          • view_count integer

            How many times the thread was opened.

            Minimum value is 0.

          • created_at string(date-time) Required

            When the thread was opened.

          • updated_at string(date-time)

            When the thread row last changed for any reason.

          • edited_at string(date-time) | null

            When the author last edited the opening message. Null when it was never edited, which is what drives the edited marker in the product.

          • last_activity_at string(date-time) Required

            When the thread last received a reply, or when it was opened if it never did. This is the sort key for the thread list.

        • stats object

          Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

          Additional properties are NOT allowed.

          Hide stats attributes Show stats attributes object
          • likes integer Required

            How many people liked the article.

            Minimum value is 0.

          • comments integer Required

            Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

            Minimum value is 0.

          • highlights integer Required

            How many passages readers highlighted.

            Minimum value is 0.

        • created_at string(date-time) Required

          When the row was created in Commune.

        • updated_at string(date-time)

          When the article was last edited.

        A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

        Hide attributes Show attributes
        • object string Required

          Always thread.

          Value is thread.

        • id string(uuid) Required

          Stable identifier.

        • short_id string | null

          Eight character base62 identifier used by the thread's own URL at /n/{handle}/chat/{short_id}. Null for a thread Commune opened under an article, which is reached through the article instead.

        • newsletter object | null Required

          The community this thread lives in. A Ref unless newsletter is named in ?expand=.

          One of:
          Ref object | null Newsletter object

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

          Hide attributes Show attributes
          • object string Required

            Always newsletter.

            Value is newsletter.

          • id string(uuid) Required

            Stable identifier.

          • handle string Required

            The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

          • name string Required

            Display name, as the creator writes it.

          • description string | null

            The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

          • esp string Required

            Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

            Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

          • image_url string(uri) | null

            Square avatar for the newsletter.

          • website_url string(uri) | null

            The creator's own site, if they linked one.

          • social_links object

            The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

            Additional properties are NOT allowed.

            Hide social_links attributes Show social_links attributes object
            • twitter string(uri)

              X or Twitter profile URL.

            • bluesky string(uri)

              Bluesky profile URL.

            • linkedin string(uri)

              LinkedIn profile URL.

            • mastodon string(uri)

              Mastodon profile URL, including the instance host.

            • youtube string(uri)

              YouTube channel URL.

            • instagram string(uri)

              Instagram profile URL.

            • threads string(uri)

              Threads profile URL.

            • github string(uri)

              GitHub profile URL.

          • language string | null

            Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

          • chat_create_permission string

            Who may start a new chat thread in this community.

            Values are editors, subscribers, or anyone.

          • allow_non_subscriber_chat boolean

            Whether people who have not subscribed may reply in existing threads.

          • owner object | null

            The account that owns the newsletter. A Ref unless owner is named in ?expand=.

            Any of:
            Ref object | null User object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

            Hide attributes Show attributes
            • object string Required

              Always user.

              Value is user.

            • id string Required

              Stable identifier.

            • username string | null

              The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

            • display_name string | null

              The name shown next to their messages and bylines.

            • avatar string(uri) | null

              Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

          • featured_article object | null

            The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

            One of:
            Ref object | null Article object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

            Hide attributes Show attributes
            • object string Required

              Always article.

              Value is article.

            • id string(uuid) Required

              Stable identifier.

            • short_id string Required

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

            • slug string 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.

            • newsletter object | null Required

              The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

              One of:
              Ref object | null Newsletter object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

              Additional properties are NOT allowed.

            • title string | null

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

            • preview_text string | null

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

            • image_url string(uri) | null

              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_url string(uri) | null

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

            • status string 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.

              Values are draft, scheduled, sending, sent, failed, or archived.

            • is_imported boolean Required

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

            • posted_at string(date-time) | null

              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_for string(date-time) | null

              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.

            • authors array[object]

              The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • thread object | null

              The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

              One of:
              Ref object | null Thread object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

              Additional properties are NOT allowed.

            • stats object

              Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

              Additional properties are NOT allowed.

              Hide stats attributes Show stats attributes object
              • likes integer Required

                How many people liked the article.

                Minimum value is 0.

              • comments integer Required

                Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

                Minimum value is 0.

              • highlights integer Required

                How many passages readers highlighted.

                Minimum value is 0.

            • created_at string(date-time) Required

              When the row was created in Commune.

            • updated_at string(date-time)

              When the article was last edited.

          • created_at string(date-time) Required

            When the newsletter was connected to or created on Commune.

          • updated_at string(date-time)

            When the profile last changed.

        • author object | null

          Who opened the thread. A Ref unless author is named in ?expand=.

          Any of:
          Ref object | null User object

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

          Hide attributes Show attributes
          • object string Required

            Always user.

            Value is user.

          • id string Required

            Stable identifier.

          • username string | null

            The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

          • display_name string | null

            The name shown next to their messages and bylines.

          • avatar string(uri) | null

            Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

        • content string Required

          The opening message. HTML, since people format what they write. Treat it as untrusted markup and render it in a sandboxed context.

        • media array[object]

          Attachments on the opening message.

          Hide media attributes Show media attributes object

          An image or file attached to a thread or a message.

          • url string(uri) Required

            Where the attachment is served from.

          • type string | null

            The attachment's media type when Commune recorded one, for example image/png. Null for an attachment old enough that none was recorded.

          • thumbnail string(uri) | null

            A smaller rendition, when one was generated.

        • visibility string Required

          Where a thread is placed. public puts it on the global Commune feed and makes it readable by anyone. subscribers keeps it inside the newsletter. Set and changed by the newsletter's team.

          A third value, paid, was in this enum until 2026-10-10. It was never produced by anything and no thread ever carried it, so it was removed rather than left as a state consumers had to handle. See Removals under Versioning.

          Values are public or subscribers.

        • audience_scoped boolean Required

          true when this thread is a private room: it was scoped to one or more of the newsletter's subscriber segments, and only the people holding one of those segments and the newsletter's team can read it or its replies. Evaluated live, so losing the segment takes the conversation away on the next request.

          A private thread is never on the global feed, so visibility is subscribers whenever this is true. Scoping a public thread to a room moves it to subscribers in the same write.

          Always present. It says that the conversation is private without saying to whom, which is why every credential that can read the thread gets it while audience_tag_ids is narrower.

        • audience_tag_ids array[string(uuid)] | null

          Which segments the thread is private to, by tag id, or null when it is not private. The semantics are OR: holding any one of them is enough.

          Present only for a credential holding audience: read on this newsletter. A thread is content, and the words in it come back to any credential the thread's own gate admits; which segments it was addressed to is the audience family's fact, priced at audience: read everywhere else a credential can ask for it (GET /newsletters/{newsletter}/tags, GET /tags/{tag}). So a credential without that family sees audience_scoped and not this property, and cannot read a creator's segmentation off a conversation. Absent and null are different answers: absent is "this credential may not read it", null is "there is none".

          Every id here is a tag with is_room set, because that is the only kind a thread can be scoped to. A tag that was since retired or un-roomed stays in the list and goes on deciding who may read the thread, exactly as it goes on deciding the audience of an article it was addressed to.

        • is_article_thread boolean Required

          true when Commune opened this thread under an article rather than a person starting it. These are kept off the global feed, because the article card already represents the conversation there.

        • article object | null

          The article that opened this thread, when is_article_thread is true. null otherwise. A Ref unless article is named in ?expand=.

          One of:
          Ref object | null Article object | null

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

          Hide attributes Show attributes
          • object string Required

            Always article.

            Value is article.

          • id string(uuid) Required

            Stable identifier.

          • short_id string Required

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

          • slug string 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.

          • newsletter object | null Required

            The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

            One of:
            Ref object | null Newsletter object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

            Hide attributes Show attributes
            • object string Required

              Always newsletter.

              Value is newsletter.

            • id string(uuid) Required

              Stable identifier.

            • handle string Required

              The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

            • name string Required

              Display name, as the creator writes it.

            • description string | null

              The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

            • esp string Required

              Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

              Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

            • image_url string(uri) | null

              Square avatar for the newsletter.

            • website_url string(uri) | null

              The creator's own site, if they linked one.

            • social_links object

              The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

              Additional properties are NOT allowed.

              Hide social_links attributes Show social_links attributes object
              • twitter string(uri)

                X or Twitter profile URL.

              • bluesky string(uri)

                Bluesky profile URL.

              • linkedin string(uri)

                LinkedIn profile URL.

              • mastodon string(uri)

                Mastodon profile URL, including the instance host.

              • youtube string(uri)

                YouTube channel URL.

              • instagram string(uri)

                Instagram profile URL.

              • threads string(uri)

                Threads profile URL.

              • github string(uri)

                GitHub profile URL.

            • language string | null

              Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

            • chat_create_permission string

              Who may start a new chat thread in this community.

              Values are editors, subscribers, or anyone.

            • allow_non_subscriber_chat boolean

              Whether people who have not subscribed may reply in existing threads.

            • owner object | null

              The account that owns the newsletter. A Ref unless owner is named in ?expand=.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • featured_article object | null

              The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

              One of:
              Ref object | null Article object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

            • created_at string(date-time) Required

              When the newsletter was connected to or created on Commune.

            • updated_at string(date-time)

              When the profile last changed.

          • title string | null

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

          • preview_text string | null

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

          • image_url string(uri) | null

            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_url string(uri) | null

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

          • status string 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.

            Values are draft, scheduled, sending, sent, failed, or archived.

          • is_imported boolean Required

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

          • posted_at string(date-time) | null

            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_for string(date-time) | null

            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.

          • authors array[object]

            The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

            Any of:
            Ref object | null User object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

            Hide attributes Show attributes
            • object string Required

              Always user.

              Value is user.

            • id string Required

              Stable identifier.

            • username string | null

              The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

            • display_name string | null

              The name shown next to their messages and bylines.

            • avatar string(uri) | null

              Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

          • thread object | null

            The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

            One of:
            Ref object | null Thread object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

            Additional properties are NOT allowed.

          • stats object

            Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

            Additional properties are NOT allowed.

            Hide stats attributes Show stats attributes object
            • likes integer Required

              How many people liked the article.

              Minimum value is 0.

            • comments integer Required

              Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

              Minimum value is 0.

            • highlights integer Required

              How many passages readers highlighted.

              Minimum value is 0.

          • created_at string(date-time) Required

            When the row was created in Commune.

          • updated_at string(date-time)

            When the article was last edited.

        • reply_count integer

          Undeleted replies in the thread, at any depth.

          Minimum value is 0.

        • view_count integer

          How many times the thread was opened.

          Minimum value is 0.

        • created_at string(date-time) Required

          When the thread was opened.

        • updated_at string(date-time)

          When the thread row last changed for any reason.

        • edited_at string(date-time) | null

          When the author last edited the opening message. Null when it was never edited, which is what drives the edited marker in the product.

        • last_activity_at string(date-time) Required

          When the thread last received a reply, or when it was opened if it never did. This is the sort key for the thread list.

        A reply inside a thread. Commune allows two levels: a reply to the thread, and a reply to that reply. A deleted message is omitted from every read rather than returned as a tombstone.

        Hide attributes Show attributes
        • object string Required

          Always message.

          Value is message.

        • id string(uuid) Required

          Stable identifier.

        • short_id string | null

          Eight character base62 identifier used by the message's permalink. Null for a message old enough that none was assigned.

        • thread object | null Required

          The thread this reply belongs to. A Ref unless thread is named in ?expand=.

          One of:
          Ref object | null Thread object | null

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

          Hide attributes Show attributes
          • object string Required

            Always thread.

            Value is thread.

          • id string(uuid) Required

            Stable identifier.

          • short_id string | null

            Eight character base62 identifier used by the thread's own URL at /n/{handle}/chat/{short_id}. Null for a thread Commune opened under an article, which is reached through the article instead.

          • newsletter object | null Required

            The community this thread lives in. A Ref unless newsletter is named in ?expand=.

            One of:
            Ref object | null Newsletter object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

            Hide attributes Show attributes
            • object string Required

              Always newsletter.

              Value is newsletter.

            • id string(uuid) Required

              Stable identifier.

            • handle string Required

              The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

            • name string Required

              Display name, as the creator writes it.

            • description string | null

              The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

            • esp string Required

              Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

              Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

            • image_url string(uri) | null

              Square avatar for the newsletter.

            • website_url string(uri) | null

              The creator's own site, if they linked one.

            • social_links object

              The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

              Additional properties are NOT allowed.

              Hide social_links attributes Show social_links attributes object
              • twitter string(uri)

                X or Twitter profile URL.

              • bluesky string(uri)

                Bluesky profile URL.

              • linkedin string(uri)

                LinkedIn profile URL.

              • mastodon string(uri)

                Mastodon profile URL, including the instance host.

              • youtube string(uri)

                YouTube channel URL.

              • instagram string(uri)

                Instagram profile URL.

              • threads string(uri)

                Threads profile URL.

              • github string(uri)

                GitHub profile URL.

            • language string | null

              Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

            • chat_create_permission string

              Who may start a new chat thread in this community.

              Values are editors, subscribers, or anyone.

            • allow_non_subscriber_chat boolean

              Whether people who have not subscribed may reply in existing threads.

            • owner object | null

              The account that owns the newsletter. A Ref unless owner is named in ?expand=.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • featured_article object | null

              The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

              One of:
              Ref object | null Article object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

              Hide attributes Show attributes
              • object string Required

                Always article.

                Value is article.

              • id string(uuid) Required

                Stable identifier.

              • short_id string Required

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

              • slug string 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.

              • newsletter object | null Required

                The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

                One of:
                Ref object | null Newsletter object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

                Additional properties are NOT allowed.

              • title string | null

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

              • preview_text string | null

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

              • image_url string(uri) | null

                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_url string(uri) | null

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

              • status string 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.

                Values are draft, scheduled, sending, sent, failed, or archived.

              • is_imported boolean Required

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

              • posted_at string(date-time) | null

                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_for string(date-time) | null

                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.

              • authors array[object]

                The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

                Any of:
                Ref object | null User object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

                Hide attributes Show attributes
                • object string Required

                  Always user.

                  Value is user.

                • id string Required

                  Stable identifier.

                • username string | null

                  The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

                • display_name string | null

                  The name shown next to their messages and bylines.

                • avatar string(uri) | null

                  Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

              • thread object | null

                The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

                One of:
                Ref object | null Thread object | null

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

                Additional properties are NOT allowed.

              • stats object

                Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

                Additional properties are NOT allowed.

                Hide stats attributes Show stats attributes object
                • likes integer Required

                  How many people liked the article.

                  Minimum value is 0.

                • comments integer Required

                  Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

                  Minimum value is 0.

                • highlights integer Required

                  How many passages readers highlighted.

                  Minimum value is 0.

              • created_at string(date-time) Required

                When the row was created in Commune.

              • updated_at string(date-time)

                When the article was last edited.

            • created_at string(date-time) Required

              When the newsletter was connected to or created on Commune.

            • updated_at string(date-time)

              When the profile last changed.

          • author object | null

            Who opened the thread. A Ref unless author is named in ?expand=.

            Any of:
            Ref object | null User object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

            Hide attributes Show attributes
            • object string Required

              Always user.

              Value is user.

            • id string Required

              Stable identifier.

            • username string | null

              The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

            • display_name string | null

              The name shown next to their messages and bylines.

            • avatar string(uri) | null

              Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

          • content string Required

            The opening message. HTML, since people format what they write. Treat it as untrusted markup and render it in a sandboxed context.

          • media array[object]

            Attachments on the opening message.

            Hide media attributes Show media attributes object

            An image or file attached to a thread or a message.

            • url string(uri) Required

              Where the attachment is served from.

            • type string | null

              The attachment's media type when Commune recorded one, for example image/png. Null for an attachment old enough that none was recorded.

            • thumbnail string(uri) | null

              A smaller rendition, when one was generated.

          • visibility string Required

            Where a thread is placed. public puts it on the global Commune feed and makes it readable by anyone. subscribers keeps it inside the newsletter. Set and changed by the newsletter's team.

            A third value, paid, was in this enum until 2026-10-10. It was never produced by anything and no thread ever carried it, so it was removed rather than left as a state consumers had to handle. See Removals under Versioning.

            Values are public or subscribers.

          • audience_scoped boolean Required

            true when this thread is a private room: it was scoped to one or more of the newsletter's subscriber segments, and only the people holding one of those segments and the newsletter's team can read it or its replies. Evaluated live, so losing the segment takes the conversation away on the next request.

            A private thread is never on the global feed, so visibility is subscribers whenever this is true. Scoping a public thread to a room moves it to subscribers in the same write.

            Always present. It says that the conversation is private without saying to whom, which is why every credential that can read the thread gets it while audience_tag_ids is narrower.

          • audience_tag_ids array[string(uuid)] | null

            Which segments the thread is private to, by tag id, or null when it is not private. The semantics are OR: holding any one of them is enough.

            Present only for a credential holding audience: read on this newsletter. A thread is content, and the words in it come back to any credential the thread's own gate admits; which segments it was addressed to is the audience family's fact, priced at audience: read everywhere else a credential can ask for it (GET /newsletters/{newsletter}/tags, GET /tags/{tag}). So a credential without that family sees audience_scoped and not this property, and cannot read a creator's segmentation off a conversation. Absent and null are different answers: absent is "this credential may not read it", null is "there is none".

            Every id here is a tag with is_room set, because that is the only kind a thread can be scoped to. A tag that was since retired or un-roomed stays in the list and goes on deciding who may read the thread, exactly as it goes on deciding the audience of an article it was addressed to.

          • is_article_thread boolean Required

            true when Commune opened this thread under an article rather than a person starting it. These are kept off the global feed, because the article card already represents the conversation there.

          • article object | null

            The article that opened this thread, when is_article_thread is true. null otherwise. A Ref unless article is named in ?expand=.

            One of:
            Ref object | null Article object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

            Hide attributes Show attributes
            • object string Required

              Always article.

              Value is article.

            • id string(uuid) Required

              Stable identifier.

            • short_id string Required

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

            • slug string 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.

            • newsletter object | null Required

              The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

              One of:
              Ref object | null Newsletter object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

              Hide attributes Show attributes
              • object string Required

                Always newsletter.

                Value is newsletter.

              • id string(uuid) Required

                Stable identifier.

              • handle string Required

                The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

              • name string Required

                Display name, as the creator writes it.

              • description string | null

                The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

              • esp string Required

                Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

                Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

              • image_url string(uri) | null

                Square avatar for the newsletter.

              • website_url string(uri) | null

                The creator's own site, if they linked one.

              • social_links object

                The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

                Additional properties are NOT allowed.

                Hide social_links attributes Show social_links attributes object
                • twitter string(uri)

                  X or Twitter profile URL.

                • bluesky string(uri)

                  Bluesky profile URL.

                • linkedin string(uri)

                  LinkedIn profile URL.

                • mastodon string(uri)

                  Mastodon profile URL, including the instance host.

                • youtube string(uri)

                  YouTube channel URL.

                • instagram string(uri)

                  Instagram profile URL.

                • threads string(uri)

                  Threads profile URL.

                • github string(uri)

                  GitHub profile URL.

              • language string | null

                Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

              • chat_create_permission string

                Who may start a new chat thread in this community.

                Values are editors, subscribers, or anyone.

              • allow_non_subscriber_chat boolean

                Whether people who have not subscribed may reply in existing threads.

              • owner object | null

                The account that owns the newsletter. A Ref unless owner is named in ?expand=.

                Any of:
                Ref object | null User object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

                Hide attributes Show attributes
                • object string Required

                  Always user.

                  Value is user.

                • id string Required

                  Stable identifier.

                • username string | null

                  The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

                • display_name string | null

                  The name shown next to their messages and bylines.

                • avatar string(uri) | null

                  Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

              • featured_article object | null

                The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

                One of:
                Ref object | null Article object | null

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

              • created_at string(date-time) Required

                When the newsletter was connected to or created on Commune.

              • updated_at string(date-time)

                When the profile last changed.

            • title string | null

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

            • preview_text string | null

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

            • image_url string(uri) | null

              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_url string(uri) | null

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

            • status string 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.

              Values are draft, scheduled, sending, sent, failed, or archived.

            • is_imported boolean Required

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

            • posted_at string(date-time) | null

              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_for string(date-time) | null

              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.

            • authors array[object]

              The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • thread object | null

              The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

              One of:
              Ref object | null Thread object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

              Additional properties are NOT allowed.

            • stats object

              Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

              Additional properties are NOT allowed.

              Hide stats attributes Show stats attributes object
              • likes integer Required

                How many people liked the article.

                Minimum value is 0.

              • comments integer Required

                Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

                Minimum value is 0.

              • highlights integer Required

                How many passages readers highlighted.

                Minimum value is 0.

            • created_at string(date-time) Required

              When the row was created in Commune.

            • updated_at string(date-time)

              When the article was last edited.

          • reply_count integer

            Undeleted replies in the thread, at any depth.

            Minimum value is 0.

          • view_count integer

            How many times the thread was opened.

            Minimum value is 0.

          • created_at string(date-time) Required

            When the thread was opened.

          • updated_at string(date-time)

            When the thread row last changed for any reason.

          • edited_at string(date-time) | null

            When the author last edited the opening message. Null when it was never edited, which is what drives the edited marker in the product.

          • last_activity_at string(date-time) Required

            When the thread last received a reply, or when it was opened if it never did. This is the sort key for the thread list.

        • newsletter object | null Required

          The community the thread lives in, denormalised so a client does not have to walk up to it. A Ref unless newsletter is named in ?expand=.

          One of:
          Ref object | null Newsletter object

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

          Hide attributes Show attributes
          • object string Required

            Always newsletter.

            Value is newsletter.

          • id string(uuid) Required

            Stable identifier.

          • handle string Required

            The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

          • name string Required

            Display name, as the creator writes it.

          • description string | null

            The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

          • esp string Required

            Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

            Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

          • image_url string(uri) | null

            Square avatar for the newsletter.

          • website_url string(uri) | null

            The creator's own site, if they linked one.

          • social_links object

            The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

            Additional properties are NOT allowed.

            Hide social_links attributes Show social_links attributes object
            • twitter string(uri)

              X or Twitter profile URL.

            • bluesky string(uri)

              Bluesky profile URL.

            • linkedin string(uri)

              LinkedIn profile URL.

            • mastodon string(uri)

              Mastodon profile URL, including the instance host.

            • youtube string(uri)

              YouTube channel URL.

            • instagram string(uri)

              Instagram profile URL.

            • threads string(uri)

              Threads profile URL.

            • github string(uri)

              GitHub profile URL.

          • language string | null

            Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

          • chat_create_permission string

            Who may start a new chat thread in this community.

            Values are editors, subscribers, or anyone.

          • allow_non_subscriber_chat boolean

            Whether people who have not subscribed may reply in existing threads.

          • owner object | null

            The account that owns the newsletter. A Ref unless owner is named in ?expand=.

            Any of:
            Ref object | null User object

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

            Hide attributes Show attributes
            • object string Required

              Always user.

              Value is user.

            • id string Required

              Stable identifier.

            • username string | null

              The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

            • display_name string | null

              The name shown next to their messages and bylines.

            • avatar string(uri) | null

              Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

          • featured_article object | null

            The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

            One of:
            Ref object | null Article object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

            Hide attributes Show attributes
            • object string Required

              Always article.

              Value is article.

            • id string(uuid) Required

              Stable identifier.

            • short_id string Required

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

            • slug string 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.

            • newsletter object | null Required

              The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

              One of:
              Ref object | null Newsletter object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

              Additional properties are NOT allowed.

            • title string | null

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

            • preview_text string | null

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

            • image_url string(uri) | null

              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_url string(uri) | null

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

            • status string 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.

              Values are draft, scheduled, sending, sent, failed, or archived.

            • is_imported boolean Required

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

            • posted_at string(date-time) | null

              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_for string(date-time) | null

              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.

            • authors array[object]

              The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • thread object | null

              The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

              One of:
              Ref object | null Thread object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

              Hide attributes Show attributes
              • object string Required

                Always thread.

                Value is thread.

              • id string(uuid) Required

                Stable identifier.

              • short_id string | null

                Eight character base62 identifier used by the thread's own URL at /n/{handle}/chat/{short_id}. Null for a thread Commune opened under an article, which is reached through the article instead.

              • newsletter object | null Required

                The community this thread lives in. A Ref unless newsletter is named in ?expand=.

                One of:
                Ref object | null Newsletter object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

                Additional properties are NOT allowed.

              • author object | null

                Who opened the thread. A Ref unless author is named in ?expand=.

                Any of:
                Ref object | null User object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

                Hide attributes Show attributes
                • object string Required

                  Always user.

                  Value is user.

                • id string Required

                  Stable identifier.

                • username string | null

                  The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

                • display_name string | null

                  The name shown next to their messages and bylines.

                • avatar string(uri) | null

                  Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

              • content string Required

                The opening message. HTML, since people format what they write. Treat it as untrusted markup and render it in a sandboxed context.

              • media array[object]

                Attachments on the opening message.

                Hide media attributes Show media attributes object

                An image or file attached to a thread or a message.

                • url string(uri) Required

                  Where the attachment is served from.

                • type string | null

                  The attachment's media type when Commune recorded one, for example image/png. Null for an attachment old enough that none was recorded.

                • thumbnail string(uri) | null

                  A smaller rendition, when one was generated.

              • visibility string Required

                Where a thread is placed. public puts it on the global Commune feed and makes it readable by anyone. subscribers keeps it inside the newsletter. Set and changed by the newsletter's team.

                A third value, paid, was in this enum until 2026-10-10. It was never produced by anything and no thread ever carried it, so it was removed rather than left as a state consumers had to handle. See Removals under Versioning.

                Values are public or subscribers.

              • audience_scoped boolean Required

                true when this thread is a private room: it was scoped to one or more of the newsletter's subscriber segments, and only the people holding one of those segments and the newsletter's team can read it or its replies. Evaluated live, so losing the segment takes the conversation away on the next request.

                A private thread is never on the global feed, so visibility is subscribers whenever this is true. Scoping a public thread to a room moves it to subscribers in the same write.

                Always present. It says that the conversation is private without saying to whom, which is why every credential that can read the thread gets it while audience_tag_ids is narrower.

              • audience_tag_ids array[string(uuid)] | null

                Which segments the thread is private to, by tag id, or null when it is not private. The semantics are OR: holding any one of them is enough.

                Present only for a credential holding audience: read on this newsletter. A thread is content, and the words in it come back to any credential the thread's own gate admits; which segments it was addressed to is the audience family's fact, priced at audience: read everywhere else a credential can ask for it (GET /newsletters/{newsletter}/tags, GET /tags/{tag}). So a credential without that family sees audience_scoped and not this property, and cannot read a creator's segmentation off a conversation. Absent and null are different answers: absent is "this credential may not read it", null is "there is none".

                Every id here is a tag with is_room set, because that is the only kind a thread can be scoped to. A tag that was since retired or un-roomed stays in the list and goes on deciding who may read the thread, exactly as it goes on deciding the audience of an article it was addressed to.

              • is_article_thread boolean Required

                true when Commune opened this thread under an article rather than a person starting it. These are kept off the global feed, because the article card already represents the conversation there.

              • article object | null

                The article that opened this thread, when is_article_thread is true. null otherwise. A Ref unless article is named in ?expand=.

                One of:
                Ref object | null Article object | null

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

              • reply_count integer

                Undeleted replies in the thread, at any depth.

                Minimum value is 0.

              • view_count integer

                How many times the thread was opened.

                Minimum value is 0.

              • created_at string(date-time) Required

                When the thread was opened.

              • updated_at string(date-time)

                When the thread row last changed for any reason.

              • edited_at string(date-time) | null

                When the author last edited the opening message. Null when it was never edited, which is what drives the edited marker in the product.

              • last_activity_at string(date-time) Required

                When the thread last received a reply, or when it was opened if it never did. This is the sort key for the thread list.

            • stats object

              Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

              Additional properties are NOT allowed.

              Hide stats attributes Show stats attributes object
              • likes integer Required

                How many people liked the article.

                Minimum value is 0.

              • comments integer Required

                Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

                Minimum value is 0.

              • highlights integer Required

                How many passages readers highlighted.

                Minimum value is 0.

            • created_at string(date-time) Required

              When the row was created in Commune.

            • updated_at string(date-time)

              When the article was last edited.

          • created_at string(date-time) Required

            When the newsletter was connected to or created on Commune.

          • updated_at string(date-time)

            When the profile last changed.

        • author object | null

          Who wrote the reply. A Ref unless author is named in ?expand=.

          Any of:
          Ref object | null User object

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

          Hide attributes Show attributes
          • object string Required

            Always user.

            Value is user.

          • id string Required

            Stable identifier.

          • username string | null

            The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

          • display_name string | null

            The name shown next to their messages and bylines.

          • avatar string(uri) | null

            Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

        • parent object | null

          The message this one replies to, or null when it replies to the thread itself. A Ref unless parent is named in ?expand=.

          One of:
          Ref object | null Message object | null

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A reply inside a thread. Commune allows two levels: a reply to the thread, and a reply to that reply. A deleted message is omitted from every read rather than returned as a tombstone.

          Additional properties are NOT allowed.

        • quoted object | null

          The message this one quotes, when the author quoted rather than replied. null otherwise. A Ref unless quoted is named in ?expand=.

          One of:
          Ref object | null Message object | null

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A reply inside a thread. Commune allows two levels: a reply to the thread, and a reply to that reply. A deleted message is omitted from every read rather than returned as a tombstone.

          Additional properties are NOT allowed.

        • depth integer Required

          1 for a reply to the thread, 2 for a reply to a reply. Commune does not nest deeper, so a client can render the tree with a fixed two level layout.

          Minimum value is 1, maximum value is 2.

        • content string Required

          The message body as HTML. Treat it as untrusted markup and render it in a sandboxed context.

        • media array[object]

          Attachments on the message.

          Hide media attributes Show media attributes object

          An image or file attached to a thread or a message.

          • url string(uri) Required

            Where the attachment is served from.

          • type string | null

            The attachment's media type when Commune recorded one, for example image/png. Null for an attachment old enough that none was recorded.

          • thumbnail string(uri) | null

            A smaller rendition, when one was generated.

        • highlight object | null

          The passage of an article this reply is anchored to, when the reader wrote it from a highlight. null otherwise. A Ref unless highlight is named in ?expand=.

          One of:
          Ref object | null Highlight object | null

          An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

          Hide attributes Show attributes
          • object string Required

            The type of the referenced resource.

          • id string Required

            The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

          A passage of an article a reader marked. Highlights are the anchor for an inline comment, which is why one can carry a link to the message it started.

          Hide attributes Show attributes
          • object string Required

            Always highlight.

            Value is highlight.

          • id string(uuid) Required

            Stable identifier.

          • article object | null Required

            The article the passage is in. A Ref unless article is named in ?expand=.

            One of:
            Ref object | null Article object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

            Hide attributes Show attributes
            • object string Required

              Always article.

              Value is article.

            • id string(uuid) Required

              Stable identifier.

            • short_id string Required

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

            • slug string 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.

            • newsletter object | null Required

              The newsletter this article belongs to. A Ref unless newsletter is named in ?expand=.

              One of:
              Ref object | null Newsletter object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

              Hide attributes Show attributes
              • object string Required

                Always newsletter.

                Value is newsletter.

              • id string(uuid) Required

                Stable identifier.

              • handle string Required

                The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

              • name string Required

                Display name, as the creator writes it.

              • description string | null

                The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

              • esp string Required

                Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

                Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

              • image_url string(uri) | null

                Square avatar for the newsletter.

              • website_url string(uri) | null

                The creator's own site, if they linked one.

              • social_links object

                The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

                Additional properties are NOT allowed.

                Hide social_links attributes Show social_links attributes object
                • twitter string(uri)

                  X or Twitter profile URL.

                • bluesky string(uri)

                  Bluesky profile URL.

                • linkedin string(uri)

                  LinkedIn profile URL.

                • mastodon string(uri)

                  Mastodon profile URL, including the instance host.

                • youtube string(uri)

                  YouTube channel URL.

                • instagram string(uri)

                  Instagram profile URL.

                • threads string(uri)

                  Threads profile URL.

                • github string(uri)

                  GitHub profile URL.

              • language string | null

                Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

              • chat_create_permission string

                Who may start a new chat thread in this community.

                Values are editors, subscribers, or anyone.

              • allow_non_subscriber_chat boolean

                Whether people who have not subscribed may reply in existing threads.

              • owner object | null

                The account that owns the newsletter. A Ref unless owner is named in ?expand=.

                Any of:
                Ref object | null User object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

                Hide attributes Show attributes
                • object string Required

                  Always user.

                  Value is user.

                • id string Required

                  Stable identifier.

                • username string | null

                  The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

                • display_name string | null

                  The name shown next to their messages and bylines.

                • avatar string(uri) | null

                  Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

              • featured_article object | null

                The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

                One of:
                Ref object | null Article object | null

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

              • created_at string(date-time) Required

                When the newsletter was connected to or created on Commune.

              • updated_at string(date-time)

                When the profile last changed.

            • title string | null

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

            • preview_text string | null

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

            • image_url string(uri) | null

              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_url string(uri) | null

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

            • status string 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.

              Values are draft, scheduled, sending, sent, failed, or archived.

            • is_imported boolean Required

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

            • posted_at string(date-time) | null

              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_for string(date-time) | null

              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.

            • authors array[object]

              The byline, in order. Each entry is a Ref unless authors is named in ?expand=. Empty when no Commune account is credited.

              Any of:
              Ref object | null User object

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

              Hide attributes Show attributes
              • object string Required

                Always user.

                Value is user.

              • id string Required

                Stable identifier.

              • username string | null

                The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

              • display_name string | null

                The name shown next to their messages and bylines.

              • avatar string(uri) | null

                Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

            • thread object | null

              The chat thread this article opened, where its discussion lives. null when the newsletter does not open a thread per article. A Ref unless thread is named in ?expand=.

              One of:
              Ref object | null Thread object | null

              An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

              Hide attributes Show attributes
              • object string Required

                The type of the referenced resource.

              • id string Required

                The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

              A conversation in a newsletter's community, together with the message that opened it. Its replies are a separate collection.

              Hide attributes Show attributes
              • object string Required

                Always thread.

                Value is thread.

              • id string(uuid) Required

                Stable identifier.

              • short_id string | null

                Eight character base62 identifier used by the thread's own URL at /n/{handle}/chat/{short_id}. Null for a thread Commune opened under an article, which is reached through the article instead.

              • newsletter object | null Required

                The community this thread lives in. A Ref unless newsletter is named in ?expand=.

                One of:
                Ref object | null Newsletter object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A newsletter and its public profile. Nothing operational is exposed: ESP credentials, OAuth tokens, group and audience ids, feed polling state and language detection bookkeeping all stay server side.

                Hide attributes Show attributes
                • object string Required

                  Always newsletter.

                  Value is newsletter.

                • id string(uuid) Required

                  Stable identifier.

                • handle string Required

                  The short, unique, URL safe name. Resolves the public profile at /n/{handle} and is accepted anywhere {newsletter} is.

                • name string Required

                  Display name, as the creator writes it.

                • description string | null

                  The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.

                • esp string Required

                  Where a newsletter is published from. commune means Commune itself sends the email. Every other value is an email service provider whose posts Commune imports. rss covers any feed that is not one of the named providers.

                  Values are commune, beehiiv, buttondown, ghost, kit, mailcheap, mailchimp, mailerlite, rss, or substack.

                • image_url string(uri) | null

                  Square avatar for the newsletter.

                • website_url string(uri) | null

                  The creator's own site, if they linked one.

                • social_links object

                  The creator's other homes on the internet, stored as canonical profile URLs. Every key is optional and a newsletter that set none returns an empty object.

                  Additional properties are NOT allowed.

                  Hide social_links attributes Show social_links attributes object
                  • twitter string(uri)

                    X or Twitter profile URL.

                  • bluesky string(uri)

                    Bluesky profile URL.

                  • linkedin string(uri)

                    LinkedIn profile URL.

                  • mastodon string(uri)

                    Mastodon profile URL, including the instance host.

                  • youtube string(uri)

                    YouTube channel URL.

                  • instagram string(uri)

                    Instagram profile URL.

                  • threads string(uri)

                    Threads profile URL.

                  • github string(uri)

                    GitHub profile URL.

                • language string | null

                  Best known language of the newsletter's writing as a BCP 47 tag. Detected from recent articles rather than declared, so treat it as a hint. Null before enough has been published to tell.

                • chat_create_permission string

                  Who may start a new chat thread in this community.

                  Values are editors, subscribers, or anyone.

                • allow_non_subscriber_chat boolean

                  Whether people who have not subscribed may reply in existing threads.

                • owner object | null

                  The account that owns the newsletter. A Ref unless owner is named in ?expand=.

                  Any of:
                  Ref object | null User object

                  An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                  Hide attributes Show attributes
                  • object string Required

                    The type of the referenced resource.

                  • id string Required

                    The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                  A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

                  Hide attributes Show attributes
                  • object string Required

                    Always user.

                    Value is user.

                  • id string Required

                    Stable identifier.

                  • username string | null

                    The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

                  • display_name string | null

                    The name shown next to their messages and bylines.

                  • avatar string(uri) | null

                    Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

                • featured_article object | null

                  The article the creator pinned to the top of the profile, or null when none is pinned. A Ref unless featured_article is named in ?expand=.

                  One of:
                  Ref object | null Article object | null

                  An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                  Hide attributes Show attributes
                  • object string Required

                    The type of the referenced resource.

                  • id string Required

                    The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                  One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

                • created_at string(date-time) Required

                  When the newsletter was connected to or created on Commune.

                • updated_at string(date-time)

                  When the profile last changed.

              • author object | null

                Who opened the thread. A Ref unless author is named in ?expand=.

                Any of:
                Ref object | null User object

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                A person's public profile, and the whole of what this API returns about anybody other than the credential's own owner. Email address, theme, notification preferences, push subscriptions, read state and saved articles are never carried.

                Hide attributes Show attributes
                • object string Required

                  Always user.

                  Value is user.

                • id string Required

                  Stable identifier.

                • username string | null

                  The unique handle the profile resolves on at /@{username}. Null for an account that has not finished signing up.

                • display_name string | null

                  The name shown next to their messages and bylines.

                • avatar string(uri) | null

                  Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.

              • content string Required

                The opening message. HTML, since people format what they write. Treat it as untrusted markup and render it in a sandboxed context.

              • media array[object]

                Attachments on the opening message.

                Hide media attributes Show media attributes object

                An image or file attached to a thread or a message.

                • url string(uri) Required

                  Where the attachment is served from.

                • type string | null

                  The attachment's media type when Commune recorded one, for example image/png. Null for an attachment old enough that none was recorded.

                • thumbnail string(uri) | null

                  A smaller rendition, when one was generated.

              • visibility string Required

                Where a thread is placed. public puts it on the global Commune feed and makes it readable by anyone. subscribers keeps it inside the newsletter. Set and changed by the newsletter's team.

                A third value, paid, was in this enum until 2026-10-10. It was never produced by anything and no thread ever carried it, so it was removed rather than left as a state consumers had to handle. See Removals under Versioning.

                Values are public or subscribers.

              • audience_scoped boolean Required

                true when this thread is a private room: it was scoped to one or more of the newsletter's subscriber segments, and only the people holding one of those segments and the newsletter's team can read it or its replies. Evaluated live, so losing the segment takes the conversation away on the next request.

                A private thread is never on the global feed, so visibility is subscribers whenever this is true. Scoping a public thread to a room moves it to subscribers in the same write.

                Always present. It says that the conversation is private without saying to whom, which is why every credential that can read the thread gets it while audience_tag_ids is narrower.

              • audience_tag_ids array[string(uuid)] | null

                Which segments the thread is private to, by tag id, or null when it is not private. The semantics are OR: holding any one of them is enough.

                Present only for a credential holding audience: read on this newsletter. A thread is content, and the words in it come back to any credential the thread's own gate admits; which segments it was addressed to is the audience family's fact, priced at audience: read everywhere else a credential can ask for it (GET /newsletters/{newsletter}/tags, GET /tags/{tag}). So a credential without that family sees audience_scoped and not this property, and cannot read a creator's segmentation off a conversation. Absent and null are different answers: absent is "this credential may not read it", null is "there is none".

                Every id here is a tag with is_room set, because that is the only kind a thread can be scoped to. A tag that was since retired or un-roomed stays in the list and goes on deciding who may read the thread, exactly as it goes on deciding the audience of an article it was addressed to.

              • is_article_thread boolean Required

                true when Commune opened this thread under an article rather than a person starting it. These are kept off the global feed, because the article card already represents the conversation there.

              • article object | null

                The article that opened this thread, when is_article_thread is true. null otherwise. A Ref unless article is named in ?expand=.

                One of:
                Ref object | null Article object | null

                An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

                Hide attributes Show attributes
                • object string Required

                  The type of the referenced resource.

                • id string Required

                  The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

                One article of a newsletter, without its body. Every collection of articles returns this shape. GET /articles/{article} returns ArticleWithContent, which is this plus content.

              • reply_count integer

                Undeleted replies in the thread, at any depth.

                Minimum value is 0.

              • view_count integer

                How many times the thread was opened.

                Minimum value is 0.

              • created_at string(date-time) Required

                When the thread was opened.

              • updated_at string(date-time)

                When the thread row last changed for any reason.

              • edited_at string(date-time) | null

                When the author last edited the opening message. Null when it was never edited, which is what drives the edited marker in the product.

              • last_activity_at string(date-time) Required

                When the thread last received a reply, or when it was opened if it never did. This is the sort key for the thread list.

            • stats object

              Engagement counts for an article, computed at read time. These are Commune side counts, not provider side email metrics: opens, clicks and deliveries are not here.

              Additional properties are NOT allowed.

              Hide stats attributes Show stats attributes object
              • likes integer Required

                How many people liked the article.

                Minimum value is 0.

              • comments integer Required

                Replies in the article's chat thread. Commune has no separate comments store: an article's discussion is a thread like any other, so this counts the undeleted replies hanging off it. 0 when the article has no thread.

                Minimum value is 0.

              • highlights integer Required

                How many passages readers highlighted.

                Minimum value is 0.

            • created_at string(date-time) Required

              When the row was created in Commune.

            • updated_at string(date-time)

              When the article was last edited.

          • quote string Required

            The marked text itself, as plain text.

            Maximum length is 5000.

          • prefix string

            Up to two hundred characters of the text immediately before the quote. Together with suffix this re anchors the highlight when the body changed and the offsets no longer line up.

          • suffix string

            Up to two hundred characters of the text immediately after the quote.

          • start_offset integer Required

            Where the passage starts, as a character offset into the article's plain text. Always less than end_offset.

            Minimum value is 0.

          • end_offset integer Required

            Where the passage ends, as a character offset into the plain text.

            Minimum value is 1.

          • owner_key string Required

            An opaque, stable per highlighter value, scoped to this one article. Group by it to tell one reader's marks apart from another's, and count distinct values for a distinct highlighter count. It cannot be resolved to a person and does not correlate across articles: Commune does not attribute a highlight to a named reader.

          • message object | null

            The chat message the reader wrote from this passage, when they wrote one. null otherwise. A Ref unless message is named in ?expand=.

            One of:
            Ref object | null Message object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            Hide attributes Show attributes
            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

            A reply inside a thread. Commune allows two levels: a reply to the thread, and a reply to that reply. A deleted message is omitted from every read rather than returned as a tombstone.

            Additional properties are NOT allowed.

          • created_at string(date-time) Required

            When the passage was marked.

        • created_at string(date-time) Required

          When the reply was written.

        • updated_at string(date-time)

          When the row last changed for any reason.

        • edited_at string(date-time) | null

          When the author last edited the text or attachments. Not touched by reactions or other side effects, so it is a faithful edited marker.

        • reactions array[object]

          The emoji reactions on this message, one entry per distinct emoji, most used first. Empty when there are none. Each entry carries users, who left it, only when reactions is named in ?expand=.

          Hide reactions attributes Show reactions attributes object

          One emoji on a message, and how many people left it.

          • emoji string Required

            The emoji itself, as the character rather than a shortcode.

          • count integer Required

            How many people left this emoji on the message.

            Minimum value is 1.

          • users array[object]

            Who left it, in the order they did. Present only when reactions is named in ?expand=.

            Hide users attributes Show users attributes object | null

            An unexpanded relationship. Ask for the relationship in ?expand= to get the full object in its place.

            • object string Required

              The type of the referenced resource.

            • id string Required

              The referenced resource's id, in whatever form that resource's own schema declares. Most are UUIDs; a Ref whose object is user carries an account identifier, which is an opaque string and not a UUID. Compare it for equality and pass it back; do not parse it.

  • 400 application/json

    The request was malformed, and the same request will fail the same way until it is changed. param names the parameter or header at fault when there is exactly one, and allowed_values lists what it accepts when that is a finite set. The code is bad_request for every case below except the last.

    • A query parameter: one the operation does not have, a value outside its set, range or format (an unparseable cursor, an unknown expand path or fields name, an identifier that is not a UUID), or a required one left out, such as q on a search or newsletter when the credential reaches more than one.
    • The request body: not JSON, not the shape the operation reads, a property it does not write, or a value of the wrong type, length or format. param is absent here, since the body is not a parameter, and the message names the property.
    • The Idempotency-Key header, on an operation that changes something: missing, or a value this API will not store.
    • An unrecognised Commune-Version, which answers with its own code, invalid_version, because it is never fixed by changing the body.
    Hide response attribute Show response attribute object
    • error object Required

      Additional properties are NOT allowed.

      Hide error attributes Show error attributes object
      • code string Required

        The stable, machine readable reason a request failed. New codes may be added in a minor version, so treat an unrecognised code as a generic failure of its HTTP status class.

        Two of these share a status with a neighbour and exist because what a caller does next is different. invalid_version is a 400 that is never fixed by changing the request body. not_commune_newsletter is a 422 that is never fixed by changing the request at all: it says the newsletter's articles are published somewhere else and mirrored into Commune afterwards, so Commune cannot write one. Its page at https://usecommune.dev/errors/not_commune_newsletter, like every code's, is its docs_url, and it covers moving a newsletter onto Commune's own publishing, which is the only thing that resolves it.

        Values are bad_request, invalid_version, unauthorized, forbidden, insufficient_scope, payment_required, not_found, conflict, unprocessable, not_commune_newsletter, rate_limited, internal_error, or service_unavailable.

      • message string Required

        A human readable sentence describing what went wrong. Written for a developer reading a log, not for an end user. Do not branch on it, branch on code.

      • param string

        The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.

      • allowed_values array[string]

        Everything param would have accepted, when what it accepts is a finite set. Absent when it is not: a cursor, an identifier or a numeric range has nothing to enumerate, and an empty array would read as "nothing is allowed".

        It repeats what message says in prose, so a caller can correct a request from this one response: the array is what a program branches on, the sentence is what a person or a model reads.

        On an unknown parameter name rather than an unknown value, this carries the parameter names the operation does accept, since that is the set the caller has to pick from.

        On an insufficient_scope failure there is usually no parameter at fault and param is absent, and this carries the one permission that was needed, written the way the permission table writes it, such as content: read. The exception is a credential that may call the operation but not with one value of a parameter, such as ?expand=subscriber on listNewsletterInsights without audience: read: then param names the parameter and this carries the values this credential may send instead.

      • request_id string

        Identifier for this request, echoed in the Commune-Request-Id response header. Quote it in support requests.

      • docs_url string(uri)

        Link to the documentation for this error code: always https://usecommune.dev/errors/ followed by the code, a page on what the code means, what usually causes it and how to fix it.

  • 401 application/json

    No credential was presented, or it is malformed, unknown, revoked or expired, or it is an access token minted for a different audience.

    Every one of these answers identically, down to the wording and the headers, so a refusal never confirms that a string was once real.

    Hide headers attribute Show headers attribute
    • WWW-Authenticate string

      The authentication scheme this API accepts, and where to find out how to get a credential for it. Always Bearer realm="Commune API", resource_metadata="https://api.usecommune.com/.well-known/oauth-protected-resource".

      resource_metadata is the RFC 9728 pointer to this API's protected resource metadata, which names the authorization server an OAuth client should send its user to. A client holding an API key can ignore it. The header carries no error parameter, not even error="invalid_token", because it describes what this API accepts rather than what was wrong with the credential sent, and the reasons above are deliberately indistinguishable.

      There is no second scheme and no query-parameter fallback, because a credential that can travel in a URL ends up in access logs and referer headers.

    Hide response attribute Show response attribute object
    • error object Required

      Additional properties are NOT allowed.

      Hide error attributes Show error attributes object
      • code string Required

        The stable, machine readable reason a request failed. New codes may be added in a minor version, so treat an unrecognised code as a generic failure of its HTTP status class.

        Two of these share a status with a neighbour and exist because what a caller does next is different. invalid_version is a 400 that is never fixed by changing the request body. not_commune_newsletter is a 422 that is never fixed by changing the request at all: it says the newsletter's articles are published somewhere else and mirrored into Commune afterwards, so Commune cannot write one. Its page at https://usecommune.dev/errors/not_commune_newsletter, like every code's, is its docs_url, and it covers moving a newsletter onto Commune's own publishing, which is the only thing that resolves it.

        Values are bad_request, invalid_version, unauthorized, forbidden, insufficient_scope, payment_required, not_found, conflict, unprocessable, not_commune_newsletter, rate_limited, internal_error, or service_unavailable.

      • message string Required

        A human readable sentence describing what went wrong. Written for a developer reading a log, not for an end user. Do not branch on it, branch on code.

      • param string

        The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.

      • allowed_values array[string]

        Everything param would have accepted, when what it accepts is a finite set. Absent when it is not: a cursor, an identifier or a numeric range has nothing to enumerate, and an empty array would read as "nothing is allowed".

        It repeats what message says in prose, so a caller can correct a request from this one response: the array is what a program branches on, the sentence is what a person or a model reads.

        On an unknown parameter name rather than an unknown value, this carries the parameter names the operation does accept, since that is the set the caller has to pick from.

        On an insufficient_scope failure there is usually no parameter at fault and param is absent, and this carries the one permission that was needed, written the way the permission table writes it, such as content: read. The exception is a credential that may call the operation but not with one value of a parameter, such as ?expand=subscriber on listNewsletterInsights without audience: read: then param names the parameter and this carries the values this credential may send instead.

      • request_id string

        Identifier for this request, echoed in the Commune-Request-Id response header. Quote it in support requests.

      • docs_url string(uri)

        Link to the documentation for this error code: always https://usecommune.dev/errors/ followed by the code, a page on what the code means, what usually causes it and how to fix it.

  • 429 application/json

    Too many requests. Back off and retry after the interval named by the Retry-After response header.

    One of the budgets in RateLimit-Policy ran out, and the RateLimit-* headers on this response say which and when it resets.

    Hide headers attribute Show headers attribute
    • Retry-After integer

      Seconds to wait before retrying.

      Minimum value is 1.

    Hide response attribute Show response attribute object
    • error object Required

      Additional properties are NOT allowed.

      Hide error attributes Show error attributes object
      • code string Required

        The stable, machine readable reason a request failed. New codes may be added in a minor version, so treat an unrecognised code as a generic failure of its HTTP status class.

        Two of these share a status with a neighbour and exist because what a caller does next is different. invalid_version is a 400 that is never fixed by changing the request body. not_commune_newsletter is a 422 that is never fixed by changing the request at all: it says the newsletter's articles are published somewhere else and mirrored into Commune afterwards, so Commune cannot write one. Its page at https://usecommune.dev/errors/not_commune_newsletter, like every code's, is its docs_url, and it covers moving a newsletter onto Commune's own publishing, which is the only thing that resolves it.

        Values are bad_request, invalid_version, unauthorized, forbidden, insufficient_scope, payment_required, not_found, conflict, unprocessable, not_commune_newsletter, rate_limited, internal_error, or service_unavailable.

      • message string Required

        A human readable sentence describing what went wrong. Written for a developer reading a log, not for an end user. Do not branch on it, branch on code.

      • param string

        The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.

      • allowed_values array[string]

        Everything param would have accepted, when what it accepts is a finite set. Absent when it is not: a cursor, an identifier or a numeric range has nothing to enumerate, and an empty array would read as "nothing is allowed".

        It repeats what message says in prose, so a caller can correct a request from this one response: the array is what a program branches on, the sentence is what a person or a model reads.

        On an unknown parameter name rather than an unknown value, this carries the parameter names the operation does accept, since that is the set the caller has to pick from.

        On an insufficient_scope failure there is usually no parameter at fault and param is absent, and this carries the one permission that was needed, written the way the permission table writes it, such as content: read. The exception is a credential that may call the operation but not with one value of a parameter, such as ?expand=subscriber on listNewsletterInsights without audience: read: then param names the parameter and this carries the values this credential may send instead.

      • request_id string

        Identifier for this request, echoed in the Commune-Request-Id response header. Quote it in support requests.

      • docs_url string(uri)

        Link to the documentation for this error code: always https://usecommune.dev/errors/ followed by the code, a page on what the code means, what usually causes it and how to fix it.

  • 500 application/json

    Something failed inside Commune. The request may be retried.

    Hide response attribute Show response attribute object
    • error object Required

      Additional properties are NOT allowed.

      Hide error attributes Show error attributes object
      • code string Required

        The stable, machine readable reason a request failed. New codes may be added in a minor version, so treat an unrecognised code as a generic failure of its HTTP status class.

        Two of these share a status with a neighbour and exist because what a caller does next is different. invalid_version is a 400 that is never fixed by changing the request body. not_commune_newsletter is a 422 that is never fixed by changing the request at all: it says the newsletter's articles are published somewhere else and mirrored into Commune afterwards, so Commune cannot write one. Its page at https://usecommune.dev/errors/not_commune_newsletter, like every code's, is its docs_url, and it covers moving a newsletter onto Commune's own publishing, which is the only thing that resolves it.

        Values are bad_request, invalid_version, unauthorized, forbidden, insufficient_scope, payment_required, not_found, conflict, unprocessable, not_commune_newsletter, rate_limited, internal_error, or service_unavailable.

      • message string Required

        A human readable sentence describing what went wrong. Written for a developer reading a log, not for an end user. Do not branch on it, branch on code.

      • param string

        The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.

      • allowed_values array[string]

        Everything param would have accepted, when what it accepts is a finite set. Absent when it is not: a cursor, an identifier or a numeric range has nothing to enumerate, and an empty array would read as "nothing is allowed".

        It repeats what message says in prose, so a caller can correct a request from this one response: the array is what a program branches on, the sentence is what a person or a model reads.

        On an unknown parameter name rather than an unknown value, this carries the parameter names the operation does accept, since that is the set the caller has to pick from.

        On an insufficient_scope failure there is usually no parameter at fault and param is absent, and this carries the one permission that was needed, written the way the permission table writes it, such as content: read. The exception is a credential that may call the operation but not with one value of a parameter, such as ?expand=subscriber on listNewsletterInsights without audience: read: then param names the parameter and this carries the values this credential may send instead.

      • request_id string

        Identifier for this request, echoed in the Commune-Request-Id response header. Quote it in support requests.

      • docs_url string(uri)

        Link to the documentation for this error code: always https://usecommune.dev/errors/ followed by the code, a page on what the code means, what usually causes it and how to fix it.

GET /search
curl "https://api.usecommune.com/search?q=onboarding&type=article" \
  -H "Authorization: Bearer $COMMUNE_API_KEY" \
  -H "Commune-Version: 2026-08-26"
Response examples (200)
{
  "object": "list",
  "data": [
    {
      "object": "search_result",
      "type": "article",
      "title": "What newsletters get wrong about community",
      "snippet": "The moderation load is the product, not a tax on it.",
      "url": "https://example.com/p/what-newsletters-get-wrong-about-community",
      "score": 0.94,
      "resource": {
        "object": "article",
        "id": "4c9e2f81-0b7a-4d13-8e55-1a2b3c4d5e6f"
      }
    },
    {
      "object": "search_result",
      "type": "newsletter",
      "title": "The Example Letter",
      "snippet": null,
      "url": "https://usecommune.com/n/example-letter",
      "score": 0.71,
      "resource": {
        "object": "newsletter",
        "id": "7d3f1c02-58a1-4a4e-9a0b-2f6d1c9e4411"
      }
    },
    {
      "object": "search_result",
      "type": "thread",
      "title": null,
      "snippet": "The bit about moderation load matched my experience exactly.",
      "url": "https://example.com/t/k3n8qz",
      "score": 0.48,
      "resource": {
        "object": "thread",
        "id": "b1c2d3e4-f506-4718-8293-a4b5c6d7e8f9"
      }
    }
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "Y3Vyc29yOjE3NTY0MjM2MDAwMDA6MDE5MmM4"
  }
}
Response examples (400)
{
  "error": {
    "code": "bad_request",
    "message": "Newsletter not found.",
    "param": "cursor",
    "allowed_values": [
      "subscribed",
      "unsubscribed",
      "bounced",
      "complained",
      "pending"
    ],
    "request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
    "docs_url": "https://usecommune.dev/errors/not_found"
  }
}
Response examples (401)
# Headers
WWW-Authenticate: string

# Payload
{
  "error": {
    "code": "bad_request",
    "message": "Newsletter not found.",
    "param": "cursor",
    "allowed_values": [
      "subscribed",
      "unsubscribed",
      "bounced",
      "complained",
      "pending"
    ],
    "request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
    "docs_url": "https://usecommune.dev/errors/not_found"
  }
}
Response examples (429)
# Headers
Retry-After: 42

# Payload
{
  "error": {
    "code": "bad_request",
    "message": "Newsletter not found.",
    "param": "cursor",
    "allowed_values": [
      "subscribed",
      "unsubscribed",
      "bounced",
      "complained",
      "pending"
    ],
    "request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
    "docs_url": "https://usecommune.dev/errors/not_found"
  }
}
Response examples (500)
{
  "error": {
    "code": "bad_request",
    "message": "Newsletter not found.",
    "param": "cursor",
    "allowed_values": [
      "subscribed",
      "unsubscribed",
      "bounced",
      "complained",
      "pending"
    ],
    "request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
    "docs_url": "https://usecommune.dev/errors/not_found"
  }
}