Buttondown Comments API

The Comments API from Buttondown — 5 operation(s) covering subscriber comments on emails, and their moderation state.

Operations 5

POST /comments Create Comment #
GET /comments List Comments #
GET /comments/{id} Retrieve Comment #
PATCH /comments/{id} Update Comment #
DELETE /comments/{id} Delete Comment #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/buttondown-comments-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

buttondown-comments-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Buttondown Comments API
  version: 1.0.0
  description: The Buttondown API lets you manage newsletters, subscribers, emails, and more. See [the documentation](https://docs.buttondown.com/api-introduction) for guides and examples.
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
servers:
- url: https://api.buttondown.com/v1
security:
- ApiKeyAuth: []
tags:
- name: Comments
paths:
  /comments:
    post:
      operationId: create_comment
      summary: Create Comment
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Comment'
          links:
            retrieve_comment:
              operationId: retrieve_comment
              parameters:
                path.id: $response.body#/id
            update_comment:
              operationId: update_comment
              parameters:
                path.id: $response.body#/id
            delete_comment:
              operationId: delete_comment
              parameters:
                path.id: $response.body#/id
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '409':
          description: Conflict
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorMessage'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '429':
          description: Too Many Requests
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            X-RateLimit-Limit:
              description: Requests permitted per minute.
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Unix timestamp at which the window resets.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
      description: Create a new comment or reply to an existing comment. If subscriber_id is provided, the comment is attributed to that subscriber; otherwise it is attributed to the newsletter author.
      tags:
      - Comments
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommentInput'
        required: true
      security:
      - ApiKeyAuth: []
    get:
      operationId: list_comments
      summary: List Comments
      parameters:
      - in: query
        name: email_id
        schema:
          description: If provided, only return comments for the given [email](https://docs.buttondown.com/api-emails-introduction).
          example:
          - em_01h8xg4j3k2m1n0p9q8r7s6t5v
          title: Email Id
          pattern: ^(?:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|(?:em)_(?:[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))$
          type: string
        required: false
        description: If provided, only return comments for the given [email](https://docs.buttondown.com/api-emails-introduction).
        example:
        - em_01h8xg4j3k2m1n0p9q8r7s6t5v
      - in: query
        name: subscriber_id
        schema:
          description: If provided, only return comments for the given [subscriber](https://docs.buttondown.com/api-subscribers-introduction).
          example:
          - sub_01h8xg4j3k2m1n0p9q8r7s6t5v
          title: Subscriber Id
          pattern: ^(?:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|(?:sub)_(?:[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))$
          type: string
        required: false
        description: If provided, only return comments for the given [subscriber](https://docs.buttondown.com/api-subscribers-introduction).
        example:
        - sub_01h8xg4j3k2m1n0p9q8r7s6t5v
      - in: query
        name: parent_id
        schema:
          description: If provided, only return comments that are replies to the given parent comment.
          example:
          - com_01h8xg4j3k2m1n0p9q8r7s6t5v
          title: Parent Id
          pattern: ^(?:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|(?:com)_(?:[0-7][0-9abcdefghjkmnpqrstvwxyz]{25}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))$
          type: string
        required: false
        description: If provided, only return comments that are replies to the given parent comment.
        example:
        - com_01h8xg4j3k2m1n0p9q8r7s6t5v
      - in: query
        name: expand
        schema:
          description: 'If provided, expand the given field. (Only supported fields: ''subscriber'', ''email'').'
          items:
            enum:
            - subscriber
            - email
            type: string
          title: Expand
          type: array
        required: false
        description: 'If provided, expand the given field. (Only supported fields: ''subscriber'', ''email'').'
      - in: query
        name: ordering
        schema:
          allOf:
          - enum:
            - creation_date
            - -creation_date
            - email
            - -email
            - subscriber
            - -subscriber
            title: Ordering
            type: string
          default: -creation_date
          description: The ordering to apply to the results.
          example: -creation_date
        required: false
        description: The ordering to apply to the results.
        example: -creation_date
      - in: query
        name: status
        schema:
          description: If provided, only return comments with the given status. Only the newsletter owner can filter by status; subscribers always see active comments.
          $ref: '#/components/schemas/CommentStatus'
        required: false
        description: If provided, only return comments with the given status. Only the newsletter owner can filter by status; subscribers always see active comments.
      - in: query
        name: page
        required: false
        description: The page number of the paginated response.
        schema:
          type: integer
          title: Page
          description: The page number of the paginated response.
          default: 1
          example: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommentPage'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '409':
          description: Conflict
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorMessage'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '429':
          description: Too Many Requests
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            X-RateLimit-Limit:
              description: Requests permitted per minute.
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Unix timestamp at which the window resets.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
      description: List all comments
      tags:
      - Comments
      security:
      - ApiKeyAuth: []
  /comments/{id}:
    get:
      operationId: retrieve_comment
      summary: Retrieve Comment
      parameters:
      - in: path
        name: id
        schema:
          title: Id
          type: string
        required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Comment'
          links:
            update_comment:
              operationId: update_comment
              parameters:
                path.id: $response.body#/id
            delete_comment:
              operationId: delete_comment
              parameters:
                path.id: $response.body#/id
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '409':
          description: Conflict
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '429':
          description: Too Many Requests
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            X-RateLimit-Limit:
              description: Requests permitted per minute.
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Unix timestamp at which the window resets.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
      description: Retrieve a specific comment by its ID
      tags:
      - Comments
      security:
      - ApiKeyAuth: []
    patch:
      operationId: update_comment
      summary: Update Comment
      parameters:
      - in: path
        name: id
        schema:
          title: Id
          type: string
        required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Comment'
          links:
            retrieve_comment:
              operationId: retrieve_comment
              parameters:
                path.id: $response.body#/id
            delete_comment:
              operationId: delete_comment
              parameters:
                path.id: $response.body#/id
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorMessage'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '429':
          description: Too Many Requests
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            X-RateLimit-Limit:
              description: Requests permitted per minute.
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Unix timestamp at which the window resets.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
      description: Update a comment's status. Only the newsletter owner can call this.
      tags:
      - Comments
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommentUpdateInput'
        required: true
      security:
      - ApiKeyAuth: []
    delete:
      operationId: delete_comment
      summary: Delete Comment
      parameters:
      - in: path
        name: id
        schema:
          title: Id
          type: string
        required: true
      responses:
        '204':
          description: No Content
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorMessage'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '429':
          description: Too Many Requests
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
            X-RateLimit-Limit:
              description: Requests permitted per minute.
              schema:
                type: integer
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
            X-RateLimit-Reset:
              description: Unix timestamp at which the window resets.
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
      description: Delete a comment. Only the comment owner (subscriber) or the newsletter author can delete a comment.
      tags:
      - Comments
      security:
      - ApiKeyAuth: []
components:
  schemas:
    FilterGroup:
      description: "Buttondown's filtering schema can be used for multiple things:\n\n- Filtering [the audience of an email](/api-emails-create) to a specific subset\n- Creating [finely-tuned automations](/api-automation-introduction)\n\nFilters are fractal; they can be nested in groups, and groups can be nested in other groups. This is accomplished through a tree-like structure. Every \"FilterGroup\" has a \"predicate\" field, which is either \"and\" or \"or\", which determines how the filters and groups within the group are combined, a \"groups\" field, which is a list of \"FilterGroup\" objects (that's that recursive bit!), and a \"filters\" field, which are the leaf-level filters themselves.\n\nLet's say you want a simple filter: all subscribers who have a tag whose ID is `sub_tag_0j6hb7h40j6hb7h40j6hb7h40j`. You can do that like this:\n\n```json\n{\n    \"filters\": [{\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40j\"}],\n    \"groups\": [],\n    \"predicate\": \"and\"\n}\n```\n\nNow, let's say you want to filter for subscribers who have that tag and a tag whose ID is `sub_tag_0j6hb7h40j6hb7h40j6hb7h40k`. You can do that like this:\n\n```json\n{\n    \"filters\": [{\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40j\"}, {\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40k\"}],\n    \"groups\": [],\n    \"predicate\": \"and\"\n}\n```\n\nIf you wanted to change that `and` to an `or`, you can do that like this:\n\n```json\n{\n    \"filters\": [{\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40j\"}, {\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40k\"}],\n    \"groups\": [],\n    \"predicate\": \"or\"\n}\n```\n\nNow, let's say you want to filter for subscribers who have the first tag _or_ both the second tag and a third tag whose ID is `sub_tag_0j6hb7h40j6hb7h40j6hb7h40m`. This is where the whole nested thing comes in handy. You can do that like this:\n\n```json\n{\n    \"filters\": [{\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40j\"}],\n    \"groups\": [\n        {\n            \"filters\": [{\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40k\"}, {\"field\": \"subscriber.tags\", \"operator\": \"contains\", \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40m\"}],\n            \"groups\": [],\n            \"predicate\": \"and\"\n        }\n    ],\n    \"predicate\": \"or\"\n}\n```\n\nYou can read more about the specific filter construction in the [Filter documentation](/api-emails-filter)."
      properties:
        filters:
          description: The leaf-level filters to apply to the audience.
          items:
            $ref: '#/components/schemas/Filter'
          title: Filters
          type: array
        groups:
          description: The nested groups to apply to the audience.
          items:
            $ref: '#/components/schemas/FilterGroup'
          title: Groups
          type: array
        predicate:
          description: The logical operator to use when combining filters (either 'and' or 'or').
          enum:
          - and
          - or
          title: Predicate
          type: string
      required:
      - filters
      - groups
      - predicate
      title: FilterGroup
      type: object
    EmailCommentingMode:
      description: 'Governs who can comment on this email.


        This enum replaces the `is_comments_disabled` field, which has been deprecated. (Also note that this field may be superseded by newsletter-level settings; for instance, "enabled" is an invalid and inert value if the newsletter itself has comments disabled.)'
      enum:
      - disabled
      - enabled
      - enabled_for_paid_subscribers
      title: CommentingMode
      type: string
    Comment:
      description: 'Comments are a way for subscribers to interact with newsletters. They''re a way to

        provide feedback, ask questions, and generally engage with the content of an email.

        Comments exist in a tree structure; comments that reply to other comments are

        considered "children" of the parent comment.'
      properties:
        id:
          description: A unique TypeID associated with the object.
          title: Id
          type: string
        creation_date:
          description: The date and time at which the object was first created.
          format: date-time
          title: Creation Date
          type: string
        email_id:
          description: The ID of the email this comment is attached to.
          title: Email Id
          type: string
        subscriber_id:
          anyOf:
          - type: string
          - type: 'null'
          description: The ID of the subscriber who posted the comment, or null if posted by the newsletter author.
          title: Subscriber Id
        parent_id:
          anyOf:
          - type: string
          - type: 'null'
          description: The ID of the parent comment, if this comment is a reply to another comment.
          title: Parent Id
        text:
          description: The text content of the comment.
          title: Text
          type: string
        status:
          $ref: '#/components/schemas/CommentStatus'
          description: The moderation status of the comment (e.g. `active`, `spammy`).
        subscriber:
          anyOf:
          - $ref: '#/components/schemas/Subscriber'
          - type: 'null'
        email:
          anyOf:
          - $ref: '#/components/schemas/Email'
          - type: 'null'
      required:
      - id
      - creation_date
      - email_id
      - text
      - status
      title: Comment
      type: object
    SubscriberSource:
      description: 'Represents the original provenance of a subscriber. This value is not exposed

        to subscribers; it''s only used for internal tracking purposes and governs some

        of the behavior of the subscriber (i.e. whether or not to require double

        opt-in.)'
      enum:
      - admin
      - api
      - carrd
      - comment
      - embedded_form
      - form
      - import
      - memberful
      - netlify
      - organic
      - patreon
      - shopify
      - stripe
      - user
      - zapier
      title: Source
      type: string
    EmailStatus:
      description: 'Represents the state of an email.


        No action is required to move from one state or another; Buttondown

        internally handles the transitions, and exposing the status is for

        observability purposes only.'
      enum:
      - draft
      - managed_by_rss
      - about_to_send
      - scheduled
      - in_flight
      - paused
      - deleted
      - errored
      - sent
      - imported
      - throttled
      - resending
      - transactional
      - suppressed
      title: Status
      type: string
    Filter:
      description: "A filter is a single condition that can be evaluated against a [Subscriber](/api-subscribers-retrieve). It has a field, an operator, and a value:\n\n```json\n{\n    \"field\": \"subscriber.tags\",\n    \"operator\": \"contains\",\n    \"value\": \"sub_tag_0j6hb7h40j6hb7h40j6hb7h40j\"\n}\n```\n\nThe field is the path to the field on the subscriber to evaluate. The operator is the operator to use when evaluating the filter. The value is the value to compare the field to. Tag filters require the tag's ID (either a UUID or TypeID), not its name."
      properties:
        field:
          title: Field
          type: string
        operator:
          $ref: '#/components/schemas/Operator'
        value:
          title: Value
          type: string
      required:
      - field
      - operator
      - value
      title: Filter
      type: object
    ValidationErrorMessage:
      properties:
        detail:
          description: A list of validation errors.
          items:
            $ref: '#/components/schemas/ValidationErrorDetail'
          title: Detail
          type: array
      required:
      - detail
      title: ValidationErrorMessage
      type: object
    Operator:
      enum:
      - equals
      - not_equals
      - contains
      - not_contains
      - is_empty
      - is_not_empty
      - greater_than
      - less_than
      title: Operator
      type: string
      description: An enumeration.
    FirewallReasonCode:
      enum:
      - email_address_capital_letters
      - email_address_cleantalk_score
      - email_address_contains_prohibited_string
      - email_address_domain_burst
      - email_address_esp_suppression
      - email_address_extant_subscriber_count
      - email_address_gmail_word_numbers
      - email_address_has_gravatar
      - email_address_is_honeypot
      - email_address_length
      - email_address_local_part_has_many_periods
      - email_address_many_consonants_in_a_row
      - email_address_mx_record_is_valid
      - email_address_noreply_local_part
      - email_address_null_characters
      - email_address_peaceful_domain
      - email_address_plus_single_number
      - email_address_plus_variant_accounts
      - email_address_previous_evaluation
      - email_address_prohibited_via_domain
      - email_address_regex
      - email_address_sandbox_test
      - email_address_shannon_entropy
      - email_address_tied_to_account
      - email_address_typo
      - embedded_form_honeypot
      - fingerprint_missing
      - ip_address_cleantalk_score
      - ip_address_country_risk
      - ip_address_datacenter
      - ip_address_extant_subscriber_count
      - ip_address_peaceful
      - ip_address_previous_evaluation
      - ip_address_prohibited
      - metadata_has_garbage
      - newsletter_age
      - newsletter_has_customized_transactional_email
      - newsletter_has_prohibited_string
      - newsletter_status
      - project_honeypot
      - referrer_url_prohibited
      - registration_without_prior_page_visit
      - subscriber_import_provenance
      - subscriber_import_source
      - text_contains_malicious_url
      - text_contains_prohibited_string
      - turnstile_response_token_is_valid
      - user_agent_known
      - username_shannon_entropy
      title: FirewallReasonCode
      type: string
      description: An enumeration.
    Subscriber:
      description: 'Subscribers are the main way you collect email addresses and

        recipients on Buttondown. They''re what you see on your

        [subscribers page](https://buttondown.com/subscribers).


        Relevant changes to the schema:


        - [2024-08-01](https://docs.buttondown.com/api-changelog-2024-08-01): renamed `subscriber_type` and `email` to `type` and `email_address` respectively.

        - [2024-07-13](https://docs.buttondown.com/api-changelog-2024-08-01): removed `external_url` in favor of `absolute_url`.'
      properties:
        id:
          description: A unique TypeID associated with the object.
          title: Id
          type: string
        creation_date:
          description: The date and time at which the object was first created.
          format: date-time
          title: Creation Date
          type: string
        avatar_url:
          anyOf:
          - type: string
          - type: 'null'
          description: URL of the subscriber's avatar image (e.g. a Gravatar URL), if available.
          title: Avatar Url
        bounce_date:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          description: The date of the subscriber's most recent bounce event. May be set even if the subscriber has not yet been marked as undeliverable.
          title: Bounce Date
        bounce_reason:
          anyOf:
          - $ref: '#/components/schemas/SubscriberUndeliverabilityReason'
          - type: 'null'
          description: The reason of the subscriber's most recent bounce event. May be set even if the subscriber has not yet been marked as undeliverable.
        churn_date:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          description: When the subscriber cancelled their paid subscription, if applicable.
          title: Churn Date
        commenting_disabled:
          default: false
          description: Whether this subscriber is prevented from commenting.
          title: Commenting Disabled
          type: boolean
        country:
          anyOf:
          - type: string
          - type: 'null'
          description: The ISO 3166-1 alpha-2 country code inferred from the subscriber's IP address at signup, if available.
          example: US
          title: Country
        email_address:
          description: The email address of the subscriber.
          example: telemachus@buttondown.email
          title: Email Address
          type: string
        gift_subscription_end_date:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          description: When the subscriber's gift subscription expires, if applicable.
          title: Gift Subscription End Date
        gift_subscription_message:
          anyOf:
          - type: string
          - type: 'null'
          description: A custom message that was sent to the subscriber when the gift subscription was created.
          title: Gift Subscription Message
        ip_address:
          anyOf:
          - type: string
          - type: 'null'
          description: The IP address recorded when the subscriber signed up, if available.
          title: Ip Address
        last_click_date:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          description: When the subscriber most recently clicked a link in an email.
          title: Last Click Date
        last_open_date:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          description: When the subscriber most recently opened an email.
          title: Last Open Date
        delivered_count:
          anyOf:
          - type: integer
          - type: 'null'
          description: The number of distinct emails — both broadcasts and automation sends — delivered to this subscriber. Cached and refreshed periodically, so it may lag recent activity.
          example: 12
          title: Delivered Count
        open_count:
          anyOf:
          - type: integer
          - type: 'null'
          description: The subscriber's open count.
          example: 7
          title: Open Count
        clicked_count:
          anyOf:
          - type: integer
          - type: 'null'
          description: The subscriber's clicked count.
          example: 3
          title: Clicked Count
        open_rate:
          anyOf:
          - type: number
          - type: 'null'
          description: The subscriber's open rate, computed from engagement counts. Null if delivered_count is 0 or null.
          example: 0.5833
          title: Open Rate
        click_rate:
          anyOf:
          - type: number
          - type: 'null'
          description: The subscriber's click rate, computed from engagement counts. Null if delivered_count is 0 or null.
          example: 0.25
          title: Click Rate
        metadata:
          additionalProperties: true
          default: {}
          description: A structured key-value blob that you can use to store arbitrary data on the object. Metadata can be nested — you can store objects and arrays within your metadata. (You can [read more about metadata.](https://docs.buttondown.com/metadata))
          title: Metadata
          type: object
        notes:
          default: ''
          description: Any notes you want to attach to the subscriber. These are not publicly visible.
          title: Notes
          type: string
        purchased_by:
          anyOf:
          - type: string
          - type: 'null'
          description: The email address of the individual who purchased this subscription on behalf of the subscriber.
          title: Purchased By
        purchased_message:
          anyOf:
          - type: string
          - type: 'null'
          description: A custom message that was sent to the subscriber when the subscription was purchased on behalf of the subscriber.
          title: Purchased Messa

# --- truncated at 32 KB (61 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/buttondown/refs/heads/main/openapi/buttondown-comments-api-openapi.yml