List this newsletter's API keys Run in API Explorer
Every API key that can reach this newsletter, newest first, revoked
ones included. Needs settings: write, not read.
"Can reach" rather than "was issued for": a key can be granted every newsletter its owner runs rather than a named list, and such a key appears here too.
No response from this API ever contains a key's secret. A secret
exists in plaintext for one moment, in the reply to the person who
minted it in Commune's settings, and Commune keeps only a digest. An
entry carries key_prefix instead, the leading fifteen characters,
which tells keys apart and cannot be used as one.
self marks the entry this request was made with, which is otherwise
impossible to work out: a caller holds a secret and the rows carry ids.
It is false on every row when the request was made with an OAuth
token, since an OAuth token is not an API key and is not listed here.
Revoked keys stay in the list, so "when was that turned off, and what
was it called" stays answerable. Read live to tell the keys that still
work from the ones that do not.
There is no filter. A newsletter holds at most twenty live keys, so the collection fits in a page or two.
Headers
-
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 answers400withinvalid_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.
Path parameters
-
The newsletter's
id(a UUID) or itshandle. A handle is unique across Commune and is the identifier its public web profile uses, so it is the one to hardcode in an integration.
Query parameters
-
The
pagination.next_cursorvalue 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. -
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_cursordoes.Minimum value is
1, maximum value is100. Default value is20. -
Comma-separated list of relationship paths to inline in the response. Unexpanded relationships are returned as a reference object carrying only
idandobject. Each operation documents the paths it accepts, and an unknown path answers400. Nested paths use a dot, for examplearticle.newsletter. -
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.
idandobjectare always returned. An unknown property name answers400. Properties omitted by an operation, such ascontenton any article list, cannot be brought back withfields.
Responses
-
A page of keys, newest first.
Hide response attributes Show response attributes object
-
Always
list, so a response is self describing.Value is
list. -
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
-
Every credential that can reach this newsletter, newest first, revoked ones included, whether it names this newsletter or was granted every newsletter its owner runs, and not one of them carrying a secret:
key_prefixis the leading fifteen characters and is all that survives of one.selfmarks the single entry this request was made with, and isfalseon every entry for a request made with an OAuth access token. There is no filter on this collection, which fits in a page or two; readliveto tell the keys that still work from the ones that do not.Hide data attributes Show data attributes object
A credential, as it can be described without its secret.
The secret is not here and no parameter brings it back. Commune stores a digest of it and shows the plaintext once, to the person who minted it; after that only
key_prefixsurvives. Use this object to recognise a key, see whether anything is still calling with it, and turn it off.A key belongs to a person, not to a newsletter. It carries a list of the newsletters that person granted it, each with its own permissions, and what it can actually reach is that list intersected with what its owner can do on each of them at the moment of the request. So a key loses a newsletter the day its owner leaves that team, with nothing to revoke, and reaches nothing once the account behind it is gone.
A key can also be granted every newsletter its owner runs, now and in future, rather than a named list. Such a key appears on the list of each newsletter it reaches.
This object describes the key as it stands on one newsletter:
newsletteris the one the grant being read belongs to, andpermissionsis what that grant carries. Reading the same key through another newsletter's list reports that newsletter and its own permissions, which may be different.-
Always
api_key.Value is
api_key. -
Stable identifier. This is what addresses the key in a path; the secret never appears in a URL and never will.
- newsletter
object | null Required The newsletter this projection describes: the one whose grant
permissionswas read from. A key may hold several, so this is not "the key's newsletter" but the one it is being listed under. ARefunlessnewsletteris named in?expand=.One of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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
-
Always
newsletter.Value is
newsletter. -
Stable identifier.
-
The short, unique, URL safe name. Resolves the public profile at
/n/{handle}and is accepted anywhere{newsletter}is. -
Display name, as the creator writes it.
-
The profile blurb. Sanitised HTML, not plain text, because creators format it. Treat it as untrusted markup and render it in a sandboxed context.
-
Where a newsletter is published from.
communemeans Commune itself sends the email. Every other value is an email service provider whose posts Commune imports.rsscovers any feed that is not one of the named providers.Values are
commune,beehiiv,buttondown,ghost,kit,mailchimp,mailerlite,rss, orsubstack. -
Square avatar for the newsletter.
-
The creator's own site, if they linked one.
-
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
-
X or Twitter profile URL.
-
Bluesky profile URL.
-
LinkedIn profile URL.
-
Mastodon profile URL, including the instance host.
-
YouTube channel URL.
-
Instagram profile URL.
-
Threads profile URL.
-
GitHub profile URL.
-
-
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.
-
Who may start a new chat thread in this community.
Values are
editors,subscribers, oranyone. -
Whether people who have not subscribed may reply in existing threads.
- owner
object | null The account that owns the newsletter. A
Refunlessowneris named in?expand=.Any of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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
-
Always
user.Value is
user. -
Stable identifier.
-
The unique handle the profile resolves on at
/@{username}. Null for an account that has not finished signing up. -
The name shown next to their messages and bylines.
-
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
nullwhen none is pinned. ARefunlessfeatured_articleis named in?expand=.One of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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}returnsArticleWithContent, which is this pluscontent.Hide attributes Show attributes
-
Always
article.Value is
article. -
Stable identifier.
-
Eight character base62 identifier, unique across Commune. Safe in a URL and accepted anywhere
{article}is. -
URL segment under the newsletter, unique within it but not across Commune. The permalink is
/n/{handle}/a/{slug}. Falls back to theshort_idfor an untitled article. - newsletter
object | null Required The newsletter this article belongs to. A
Refunlessnewsletteris named in?expand=.One of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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.
-
-
Subject line of the article. Null for an untitled draft.
-
The short line email clients show after the subject, and what Commune uses as the excerpt on a card.
-
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.
-
The article's canonical URL on the newsletter's own provider, for an imported article. Null for one written in Commune.
-
Where an article is in its life. A credential holding only
readpermissions ever seessentand nothing else. An imported article is alwayssent, since Commune sees it after the provider delivered it.Values are
draft,scheduled,sending,sent,failed, orarchived. -
truewhen the article came in from the newsletter's provider,falsewhen it was written and sent in Commune. -
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.
-
When a queued article may go out. Set while
statusisscheduledand null otherwise.This is not
posted_atand 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. -
The byline, in order. Each entry is a
Refunlessauthorsis named in?expand=. Empty when no Commune account is credited.Any of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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
-
Always
user.Value is
user. -
Stable identifier.
-
The unique handle the profile resolves on at
/@{username}. Null for an account that has not finished signing up. -
The name shown next to their messages and bylines.
-
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.
nullwhen the newsletter does not open a thread per article. ARefunlessthreadis named in?expand=.One of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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
-
Always
thread.Value is
thread. -
Stable identifier.
-
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
Refunlessnewsletteris named in?expand=.One of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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
Refunlessauthoris named in?expand=.Any of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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
-
Always
user.Value is
user. -
Stable identifier.
-
The unique handle the profile resolves on at
/@{username}. Null for an account that has not finished signing up. -
The name shown next to their messages and bylines.
-
Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.
-
-
The opening message. HTML, since people format what they write. Treat it as untrusted markup and render it in a sandboxed context.
-
Attachments on the opening message.
Hide media attributes Show media attributes object
An image or file attached to a thread or a message.
-
Where the attachment is served from.
-
The attachment's media type when Commune recorded one, for example
image/png. Null for an attachment old enough that none was recorded. -
A smaller rendition, when one was generated.
-
-
Where a thread is placed.
publicputs it on the global Commune feed and makes it readable by anyone.subscriberskeeps it inside the newsletter.paidnarrows it further to the paying part of the audience. Set and changed by the newsletter's team.Values are
public,subscribers, orpaid. -
truewhen 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_threadistrue.nullotherwise. ARefunlessarticleis named in?expand=.One of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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}returnsArticleWithContent, which is this pluscontent. -
-
Undeleted replies in the thread, at any depth.
Minimum value is
0. -
How many times the thread was opened.
Minimum value is
0. -
When the thread was opened.
-
When the thread row last changed for any reason.
-
When the author last edited the opening message. Null when it was never edited, which is what drives the edited marker in the product.
-
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.
-
-
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
-
How many people liked the article.
Minimum value is
0. -
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.
0when the article has no thread.Minimum value is
0. -
How many passages readers highlighted.
Minimum value is
0.
-
-
When the row was created in Commune.
-
When the article was last edited.
-
-
When the newsletter was connected to or created on Commune.
-
When the profile last changed.
-
-
What the creator called it when they minted it. Not unique: two keys called
stagingare a creator's problem and not an error. -
The leading fifteen characters of the secret, which is all of it that Commune keeps. Enough to recognise which key an integration is configured with, and short enough that it is not itself usable.
-
What this key was granted on the newsletter above. Six families, each
none,readorwrite.A key can be granted more than one newsletter and can carry different permissions on each, so this is the grant for the newsletter this row is being served under and not a property of the key on its own. An operation this key does not hold the family for answers
403naming the family and the level it needed.Additional properties are NOT allowed.
Hide permissions attributes Show permissions attributes object
-
Articles, the passages readers marked in them, threads and messages.
Values are
none,read, orwrite. -
Subscribers, the segments they are in, and the community roster. The one family whose rows carry email addresses.
Values are
none,read, orwrite. -
Sending an article, the addresses it goes out from, the domains behind them, and the log of what was delivered where.
Values are
none,read, orwrite. -
Engagement scores, events and the computed metrics over them.
Values are
none,read, orwrite. -
The newsletter's configuration, its team and its credentials. Reading the credential list is the first half of turning one off, so the credential operations need
writehere rather thanread.Values are
none,read, orwrite. -
Event destinations and the portal session that edits them.
Values are
none,read, orwrite.
-
-
The contract version a request made with this key resolves to when it sends no
Commune-Versionheader. Stamped when the key was minted, so a newer contract shipping does not move an existing integration. -
Whether a request made with this key right now would be authenticated. False once it has been revoked, and false once it has expired. Computed against Commune's own clock with the same test the authentication path applies, so it is a more reliable answer than comparing
expires_atto a client's clock. -
Whether somebody turned this key off. A revoked key never becomes live again: nothing in this API can revive one.
-
When it was turned off, or null while it is not. A second revocation does not move it.
-
When the key stops working on its own, or null for one that never does. Expiry and revocation are separate: an expired key has not been revoked and reports
revokedfalse. -
The last time a request was authenticated with this key, or null if none ever has been. Written at most once a minute, so it is accurate to the minute rather than to the request, which is the resolution the question behind it needs: is anything still calling with this, and can it be revoked.
-
True for the one key the current request was made with, and false for every other. A caller holds a secret rather than an id, so this is the only way it can tell which of these rows is itself, which is what it needs before revoking any of them. False on every row for a request made with an OAuth access token, since no key is that credential.
- created_by
object | null The team member who minted it, or null if that account has since been removed. The key belongs to the newsletter rather than to the person, so it keeps working either way. A
Refunlesscreated_byis named in?expand=.Any of: An unexpanded relationship. Ask for the relationship in
?expand=to get the full object in its place.Hide attributes Show attributes
-
The type of the referenced resource.
-
The referenced resource's
id, in whatever form that resource's own schema declares. Most are UUIDs; aRefwhoseobjectisusercarries 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
-
Always
user.Value is
user. -
Stable identifier.
-
The unique handle the profile resolves on at
/@{username}. Null for an account that has not finished signing up. -
The name shown next to their messages and bylines.
-
Profile picture. Commune falls back to a generated avatar when the person never set one, so this is rarely null in practice.
-
-
When the key was minted.
-
-
-
The request was malformed, and the same request will fail the same way until it is changed.
paramnames the parameter or header at fault when there is exactly one, andallowed_valueslists what it accepts when that is a finite set. The code isbad_requestfor 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
expandpath orfieldsname, an identifier that is not a UUID), or a required one left out, such asqon a search ornewsletterwhen 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.
paramis absent here, since the body is not a parameter, and the message names the property. - The
Idempotency-Keyheader, 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
-
Additional properties are NOT allowed.
Hide error attributes Show error attributes object
-
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_versionis a400that is never fixed by changing the request body.not_commune_newsletteris a422that 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 athttps://usecommune.dev/errors/not_commune_newsletter, like every code's, is itsdocs_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, orservice_unavailable. -
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. -
The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.
-
Everything
paramwould 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
messagesays 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_scopefailure there is usually no parameter at fault andparamis absent, and this carries the one permission that was needed, written the way the permission table writes it, such ascontent: read. The exception is a credential that may call the operation but not with one value of a parameter, such as?expand=subscriberonlistNewsletterInsightswithoutaudience: read: thenparamnames the parameter and this carries the values this credential may send instead. -
Identifier for this request, echoed in the
Commune-Request-Idresponse header. Quote it in support requests. -
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.
-
- A query parameter: one the operation does not have, a value
outside its set, range or format (an unparseable cursor, an unknown
-
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
-
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_metadatais 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 noerrorparameter, not evenerror="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
-
Additional properties are NOT allowed.
Hide error attributes Show error attributes object
-
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_versionis a400that is never fixed by changing the request body.not_commune_newsletteris a422that 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 athttps://usecommune.dev/errors/not_commune_newsletter, like every code's, is itsdocs_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, orservice_unavailable. -
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. -
The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.
-
Everything
paramwould 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
messagesays 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_scopefailure there is usually no parameter at fault andparamis absent, and this carries the one permission that was needed, written the way the permission table writes it, such ascontent: read. The exception is a credential that may call the operation but not with one value of a parameter, such as?expand=subscriberonlistNewsletterInsightswithoutaudience: read: thenparamnames the parameter and this carries the values this credential may send instead. -
Identifier for this request, echoed in the
Commune-Request-Idresponse header. Quote it in support requests. -
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.
-
-
-
The credential is valid but is not allowed to do this. Two codes answer with this status, and
error.codesays which.insufficient_scope: it does not hold the permission. The operation needs, say,audience: readon the newsletter addressed, and this credential holds less than that there.allowed_valuescarries the permission that was needed, and the message says what the credential does hold on that newsletter, because a credential granted the wrong family and a credential belonging to somebody whose standing on the team has narrowed look identical without it. The answer can differ per newsletter: the same credential may be allowed here and refused on the next one it reaches.The same code answers an operation that needs the account permission from a credential that does not carry it. That permission is about the person a credential belongs to rather than about any newsletter, so nothing granted on a newsletter adds up to it. It is granted on the credential itself, when a key is minted or when an authorization asks for
account:read.And it answers a parameter the credential may send, but not with the value it sent: a filter a credential holding only
readpermissions may not use, or anexpandpath whose rows need a permission the operation does not.paramnames the parameter, andallowed_valuescarries what this credential may send instead, or is absent when it may send nothing there at all.forbidden: it may not act here at all. Either the credential does not reach the newsletter addressed, because it was never granted it or because the person it belongs to can no longer act on it, or it reaches no newsletter at all;paramisnewsletter, andGET /newsletterslists the ones it does reach. Or, onDELETE /api-keys/{key}, the credential named belongs to somebody else. Neither carriesallowed_values, because there is no value to send instead.Hide response attribute Show response attribute object
-
Additional properties are NOT allowed.
Hide error attributes Show error attributes object
-
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_versionis a400that is never fixed by changing the request body.not_commune_newsletteris a422that 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 athttps://usecommune.dev/errors/not_commune_newsletter, like every code's, is itsdocs_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, orservice_unavailable. -
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. -
The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.
-
Everything
paramwould 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
messagesays 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_scopefailure there is usually no parameter at fault andparamis absent, and this carries the one permission that was needed, written the way the permission table writes it, such ascontent: read. The exception is a credential that may call the operation but not with one value of a parameter, such as?expand=subscriberonlistNewsletterInsightswithoutaudience: read: thenparamnames the parameter and this carries the values this credential may send instead. -
Identifier for this request, echoed in the
Commune-Request-Idresponse header. Quote it in support requests. -
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.
-
-
-
No such resource, or the key is not allowed to know that it exists. Commune answers
404rather than403where distinguishing the two would leak the existence of private content.Hide response attribute Show response attribute object
-
Additional properties are NOT allowed.
Hide error attributes Show error attributes object
-
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_versionis a400that is never fixed by changing the request body.not_commune_newsletteris a422that 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 athttps://usecommune.dev/errors/not_commune_newsletter, like every code's, is itsdocs_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, orservice_unavailable. -
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. -
The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.
-
Everything
paramwould 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
messagesays 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_scopefailure there is usually no parameter at fault andparamis absent, and this carries the one permission that was needed, written the way the permission table writes it, such ascontent: read. The exception is a credential that may call the operation but not with one value of a parameter, such as?expand=subscriberonlistNewsletterInsightswithoutaudience: read: thenparamnames the parameter and this carries the values this credential may send instead. -
Identifier for this request, echoed in the
Commune-Request-Idresponse header. Quote it in support requests. -
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.
-
-
-
Too many requests. Back off and retry after the interval named by the
Retry-Afterresponse header.One of the budgets in
RateLimit-Policyran out, and theRateLimit-*headers on this response say which and when it resets.Hide headers attribute Show headers attribute
Hide response attribute Show response attribute object
-
Additional properties are NOT allowed.
Hide error attributes Show error attributes object
-
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_versionis a400that is never fixed by changing the request body.not_commune_newsletteris a422that 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 athttps://usecommune.dev/errors/not_commune_newsletter, like every code's, is itsdocs_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, orservice_unavailable. -
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. -
The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.
-
Everything
paramwould 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
messagesays 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_scopefailure there is usually no parameter at fault andparamis absent, and this carries the one permission that was needed, written the way the permission table writes it, such ascontent: read. The exception is a credential that may call the operation but not with one value of a parameter, such as?expand=subscriberonlistNewsletterInsightswithoutaudience: read: thenparamnames the parameter and this carries the values this credential may send instead. -
Identifier for this request, echoed in the
Commune-Request-Idresponse header. Quote it in support requests. -
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.
-
-
-
Something failed inside Commune. The request may be retried.
Hide response attribute Show response attribute object
-
Additional properties are NOT allowed.
Hide error attributes Show error attributes object
-
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_versionis a400that is never fixed by changing the request body.not_commune_newsletteris a422that 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 athttps://usecommune.dev/errors/not_commune_newsletter, like every code's, is itsdocs_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, orservice_unavailable. -
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. -
The query, path or body parameter the error is attributed to, when the error is attributable to exactly one. Absent otherwise.
-
Everything
paramwould 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
messagesays 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_scopefailure there is usually no parameter at fault andparamis absent, and this carries the one permission that was needed, written the way the permission table writes it, such ascontent: read. The exception is a credential that may call the operation but not with one value of a parameter, such as?expand=subscriberonlistNewsletterInsightswithoutaudience: read: thenparamnames the parameter and this carries the values this credential may send instead. -
Identifier for this request, echoed in the
Commune-Request-Idresponse header. Quote it in support requests. -
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.
-
-
curl \
--request GET 'https://api.usecommune.com/newsletters/9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e/api-keys' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "Commune-Version: 2026-08-26"
{
"object": "list",
"data": [
{
"object": "api_key",
"id": "9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b",
"newsletter": {
"object": "newsletter",
"id": "7d3f1c02-58a1-4a4e-9a0b-2f6d1c9e4411"
},
"name": "Warehouse sync",
"key_prefix": "cmn_sk_7Qd2xLpA",
"permissions": {
"content": "write",
"audience": "write",
"sending": "write",
"insights": "write",
"settings": "write",
"webhooks": "write"
},
"pinned_version": "2026-08-26",
"live": true,
"revoked": false,
"revoked_at": null,
"expires_at": null,
"last_used_at": "2026-09-08T09:41:22Z",
"self": true,
"created_by": {
"object": "user",
"id": "usr_2Nf8Kq1pWc"
},
"created_at": "2026-08-27T11:02:44Z"
},
{
"object": "api_key",
"id": "8e9f0a1b-2c3d-4e4f-9a5b-6c7d8e9f0a1b",
"newsletter": {
"object": "newsletter",
"id": "7d3f1c02-58a1-4a4e-9a0b-2f6d1c9e4411"
},
"name": "Old website widget",
"key_prefix": "cmn_sk_3Vn6yTgH",
"permissions": {
"content": "read",
"audience": "none",
"sending": "none",
"insights": "none",
"settings": "none",
"webhooks": "none"
},
"pinned_version": "2026-08-26",
"live": false,
"revoked": true,
"revoked_at": "2026-09-01T08:12:00Z",
"expires_at": null,
"last_used_at": "2026-08-31T22:47:10Z",
"self": false,
"created_by": {
"object": "user",
"id": "usr_5Qw8Hn2vFd"
},
"created_at": "2026-08-26T17:19:30Z"
}
],
"pagination": {
"has_more": false,
"next_cursor": null
}
}
{
"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"
}
}
# 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"
}
}
{
"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"
}
}
{
"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"
}
}
# 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"
}
}
{
"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"
}
}