Revoke an API key Run in API Explorer

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
DELETE /api-keys/{key}

Stops this credential working. The next request made with it is refused the same way a string that was never issued is refused.

The row survives. DELETE stamps the key as revoked rather than removing it, so it stays in the list with its revoked_at. Nothing in this API removes a key.

Revocation only goes one way. No operation here revives a revoked key, and none mints a new one, so through this API the set of working credentials on a newsletter can only get smaller. Mint a replacement in Commune's settings.

A key may revoke itself, which is what an integration that knows it has leaked, or a job finished with its credential, should do. self on the list operation says which key that is.

A key may also revoke its siblings: the other credentials belonging to the same person.

A credential belonging to somebody else answers 403, even when it reaches the same newsletter and GET /api-keys/{key} returns it. Cutting a credential off one newsletter rather than off everything is done in Commune's settings instead.

Revoking a key that is already revoked succeeds and returns it unchanged, with its original revoked_at, so a retry after a dropped response is not a failure.

Never refused for payment, so no 402. Publishes no event: the credential that was revoked learns it on its next request.

Headers

  • Idempotency-Key string Required

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

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

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

    Required, not optional.

    Minimum length is 1, maximum length is 255.

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

Path parameters

  • key string(uuid) Required

    The API key's id. Never the secret itself: Commune does not store one and could not look a key up by one, and a credential that travelled in a URL would end up in access logs and browser history.

Responses

  • 200 application/json

    The key, as it now stands. revoked is true, live is false, and revoked_at is when it was first turned off.

    Hide response attributes Show response attributes object
    • object string Required

      Always api_key.

      Value is api_key.

    • id string(uuid) Required

      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 permissions was read from. A key may hold several, so this is not "the key's newsletter" but the one it is being listed under. A Ref unless newsletter is named in ?expand=.

      One of:
    • name string Required

      What the creator called it when they minted it. Not unique: two keys called staging are a creator's problem and not an error.

    • key_prefix string Required

      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.

    • permissions object Required

      What this key was granted on the newsletter above. Six families, each none, read or write.

      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 403 naming the family and the level it needed.

      Additional properties are NOT allowed.

      Hide permissions attributes Show permissions attributes object
      • content string Required

        Articles, the passages readers marked in them, threads and messages.

        Values are none, read, or write.

      • audience string Required

        Subscribers, the segments they are in, and the community roster. The one family whose rows carry email addresses.

        Values are none, read, or write.

      • sending string Required

        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, or write.

      • insights string Required

        Engagement scores, events and the computed metrics over them.

        Values are none, read, or write.

      • settings string Required

        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 write here rather than read.

        Values are none, read, or write.

      • webhooks string Required

        Event destinations and the portal session that edits them.

        Values are none, read, or write.

    • pinned_version string(date) Required

      The contract version a request made with this key resolves to when it sends no Commune-Version header. Stamped when the key was minted, so a newer contract shipping does not move an existing integration.

    • live boolean Required

      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_at to a client's clock.

    • revoked boolean Required

      Whether somebody turned this key off. A revoked key never becomes live again: nothing in this API can revive one.

    • revoked_at string(date-time) | null

      When it was turned off, or null while it is not. A second revocation does not move it.

    • expires_at string(date-time) | null

      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 revoked false.

    • last_used_at string(date-time) | null

      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.

    • self boolean Required

      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 Ref unless created_by is named in ?expand=.

      Any of:
    • created_at string(date-time) Required

      When the key was minted.

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

  • 403 application/json

    The credential is valid but is not allowed to do this. Two codes answer with this status, and error.code says which.

    insufficient_scope: it does not hold the permission. The operation needs, say, audience: read on the newsletter addressed, and this credential holds less than that there. allowed_values carries 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 read permissions may not use, or an expand path whose rows need a permission the operation does not. param names the parameter, and allowed_values carries 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; param is newsletter, and GET /newsletters lists the ones it does reach. Or, on DELETE /api-keys/{key}, the credential named belongs to somebody else. Neither carries allowed_values, because there is no value to send instead.

    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.

  • 404 application/json

    No such resource, or the key is not allowed to know that it exists. Commune answers 404 rather than 403 where distinguishing the two would leak the existence of private content.

    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.

  • 409 application/json

    The request collided with something. On a write this is always the Idempotency-Key, in one of two ways, and the message says which.

    Either the key was already used for a different request, which is refused rather than answered with the earlier request's result. Or an earlier request using the same key has not finished, or never reported an outcome, in which case this one was not run and the key becomes usable again shortly.

    Nothing was changed by a request that answers this.

    Hide headers attribute Show headers attribute
    • Retry-After integer

      Seconds to wait before retrying, on the second case only.

      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.

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

DELETE /api-keys/{key}
curl \
 --request DELETE 'https://api.usecommune.com/api-keys/{key}' \
 --header "Authorization: Bearer $ACCESS_TOKEN" \
 --header "Idempotency-Key: 3f7c1a26-9b0e-4f5a-9a2c-2c8f1d6b4e77" \
 --header "Commune-Version: 2026-08-26"
Response examples (200)
{
  "object": "api_key",
  "id": "string",
  "newsletter": {
    "object": "newsletter",
    "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
  },
  "name": "string",
  "key_prefix": "cmn_sk_7Qd2xLpA",
  "permissions": {
    "content": "none",
    "audience": "none",
    "sending": "none",
    "insights": "none",
    "settings": "none",
    "webhooks": "none"
  },
  "pinned_version": "2026-08-26",
  "live": true,
  "revoked": true,
  "revoked_at": "2026-05-04T09:42:00Z",
  "expires_at": "2026-05-04T09:42:00Z",
  "last_used_at": "2026-05-04T09:42:00Z",
  "self": true,
  "created_by": {
    "object": "newsletter",
    "id": "9a4c1c6e-0f2b-4f47-9d3f-6d1b1a2c3d4e"
  },
  "created_at": "2026-05-04T09:42:00Z"
}
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 (403)
{
  "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 (404)
{
  "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 (409)
# 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 (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"
  }
}