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-external-feeds-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: 3.2.0
info:
title: Buttondown External Feeds 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: External Feeds
paths:
/external_feeds:
post:
operationId: create_external_feed
summary: Create External Feed
parameters: []
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/ExternalFeed'
links:
retrieve_external_feed:
operationId: retrieve_external_feed
parameters:
path.id: $response.body#/id
update_external_feed:
operationId: update_external_feed
parameters:
path.id: $response.body#/id
delete_external_feed:
operationId: delete_external_feed
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'
'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 external feed
tags:
- External Feeds
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ExternalFeedInput'
required: true
security:
- ApiKeyAuth: []
get:
operationId: list_external_feed
summary: List External Feed
parameters:
- 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/ExternalFeedPage'
'403':
description: Forbidden
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: List all external feeds
tags:
- External Feeds
security:
- ApiKeyAuth: []
/external_feeds/{id}:
patch:
operationId: update_external_feed
summary: Update External Feed
parameters:
- in: path
name: id
schema:
title: Id
type: string
required: true
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ExternalFeed'
links:
retrieve_external_feed:
operationId: retrieve_external_feed
parameters:
path.id: $response.body#/id
delete_external_feed:
operationId: delete_external_feed
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: Update an external feed's properties
tags:
- External Feeds
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ExternalFeedUpdateInput'
required: true
security:
- ApiKeyAuth: []
delete:
operationId: delete_external_feed
summary: Delete External Feed
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'
'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: Delete an external feed
tags:
- External Feeds
security:
- ApiKeyAuth: []
get:
operationId: retrieve_external_feed
summary: Retrieve External Feed
parameters:
- in: path
name: id
schema:
title: Id
type: string
required: true
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ExternalFeed'
links:
update_external_feed:
operationId: update_external_feed
parameters:
path.id: $response.body#/id
delete_external_feed:
operationId: delete_external_feed
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 external feed by its ID
tags:
- External Feeds
security:
- ApiKeyAuth: []
/external_feeds/{id}/items:
post:
operationId: poll_items
summary: Poll Items
parameters:
- in: path
name: id
schema:
title: Id
type: string
required: true
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Empty'
'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: Poll for new items in an external feed
tags:
- External Feeds
security:
- ApiKeyAuth: []
get:
operationId: retrieve_items
summary: Retrieve Items
parameters:
- in: path
name: id
schema:
title: Id
type: string
required: true
- in: query
name: expand
schema:
description: If provided, expand the given field.
items:
const: email
type: string
title: Expand
type: array
required: false
description: If provided, expand the given field.
- 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/ExternalFeedItemPage'
'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: Retrieve items from an external feed
tags:
- External Feeds
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
ExternalFeedItem:
description: 'An external feed item is a single item in an external RSS feed. It is created
automatically by Buttondown when a new item is detected in an external feed. External feed
items are immutable and cannot be modified or deleted.'
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
status:
$ref: '#/components/schemas/ExternalFeedItemStatus'
description: The processing status of this feed item.
url:
description: The canonical URL of the feed item.
title: Url
type: string
publish_date:
description: The publication date parsed from the feed item.
format: date-time
title: Publish Date
type: string
title:
description: The title of the feed item.
title: Title
type: string
description:
description: The description excerpt parsed from the feed item.
title: Description
type: string
content:
description: The full content parsed from the feed item.
title: Content
type: string
author:
description: The author name parsed from the feed item.
title: Author
type: string
email_id:
anyOf:
- type: string
- type: 'null'
description: The ID of the generated email for this feed item, if one exists.
title: Email Id
email:
anyOf:
- $ref: '#/components/schemas/Email'
- type: 'null'
description: If expanded, the email generated from this feed item.
required:
- id
- creation_date
- status
- url
- publish_date
- title
- description
- content
- author
title: ExternalFeedItem
type: object
Empty:
properties: {}
title: Empty
type: object
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
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
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.
Callout:
description: 'Surfacing-time flags about an email that the UI uses to render contextual
callouts (e.g. in the analytics panel). Computed on read; not persisted.'
enum:
- first_send_on_sending_domain
title: Callout
type: string
FailureBreakdownItem:
description: A single failure reason with its count.
properties:
code:
description: The failure reason code (e.g. 'hard_bounce', 'spam')
title: Code
type: string
count:
description: Number of failures with this reason
title: Count
type: integer
required:
- code
- count
title: FailureBreakdownItem
type: object
NewsletterEmailTemplate:
description: 'Represents the template of an email.
Each template has a different layout/style; you can view screenshots and examples [in the docs](https://docs.buttondown.com/customizing-email-design#buttondowns-default-templates).'
enum:
- classic
- custom
- modern
- plaintext
- naked
title: EmailTemplate
type: string
ArchivalMode:
description: 'Governs who can view this email in the archive.
`ARCHIVE_ONLY` is the odd one out: the email is publicly archived but
is not email content at all (e.g. an imported blog post), so it is
excluded from email-rendering contexts like "recent issues" widgets.'
enum:
- archive_only
- disabled
- enabled
- enabled_for_paid_subscribers
- enabled_for_subscribers
title: ArchivalMode
type: string
CadenceMetadata:
additionalProperties: false
properties:
time:
anyOf:
- pattern: ^([01]?[0-9]|2[0-3])$
type: string
- type: 'null'
description: Hour of the day (0-23, as a string) when emails should be generated.
title: Time
example: '9'
weekday:
anyOf:
- enum:
- monday
- tuesday
- wednesday
- thursday
- friday
- saturday
- sunday
type: string
- type: 'null'
description: Day of the week when emails should be generated. Required when cadence is `weekly`.
title: Weekday
monthday:
anyOf:
- enum:
- monday
- tuesday
- wednesday
- thursday
- friday
- saturday
- sunday
- firstday
- lastday
type: string
- pattern: ^([1-9]|[12][0-9]|3[01])$
type: string
- type: 'null'
description: Day of the month when emails should be generated. Accepts a numeric day (`1`-`31`, clamped to the last day for shorter months), a weekday name (first such day of the month), `firstday`, or `lastday`. Required when cadence is `monthly`.
title: Monthday
title: CadenceMetadata
type: object
ExternalFeedUpdateInput:
additionalProperties: false
properties:
behavior:
anyOf:
- $ref: '#/components/schemas/ExternalFeedAutomationBehavior'
description: The [behavior](https://docs.buttondown.com/api-external-feed-behavior) of the external feed.
example: draft
- type: 'null'
cadence:
anyOf:
- $ref: '#/components/schemas/ExternalFeedAutomationCadence'
description: How frequently this feed should create or draft emails.
example: daily
- type: 'null'
cadence_metadata:
anyOf:
- $ref: '#/components/schemas/CadenceMetadata'
- type: 'null'
description: Additional scheduling details for the selected cadence. `time` is required for `daily`/`weekly`/`monthly` cadences; `weekday` is required for `weekly`; `monthday` is required for `monthly`. See the [cadence metadata reference](https://docs.buttondown.com/api-external-feed-cadence-metadata) for allowed values.
filters:
anyOf:
- $ref: '#/components/schemas/FilterGroup'
description: Tag-based filtering rules used to decide which subscribers receive feed-generated emails.
- type: 'null'
subject:
anyOf:
- description: The subject line template for emails generated from this feed.
maxLength: 255
minLength: 1
type: string
- type: 'null'
title: Subject
body:
anyOf:
- description: The body template for emails generated from this feed.
minLength: 1
type: string
- type: 'null'
title: Body
label:
anyOf:
- maxLength: 255
type: string
- type: 'null'
description: An optional internal label for this feed.
title: Label
status:
anyOf:
- enum:
- active
- failing
- inactive
type: string
- type: 'null'
description: The current status of the external feed automation.
title: Status
metadata:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
description: Metadata to be passed to emails rendered by this RSS feed.
title: Metadata
example:
foo: bar
skip_old_items:
anyOf:
- type: boolean
- type: 'null'
description: Skip items with publish date older than one day from when they're discovered
title: Skip Old Items
title: ExternalFeedUpdateInput
type: object
Analytics:
properties:
recipients:
default: 0
description: The number of subscribers the email was dispatched to.
title: Recipients
type: integer
deliveries:
default: 0
description: The number of successful deliveries (recipients minus failures).
title: Deliveries
type: integer
opens:
default: 0
description: The number of unique opens recorded.
title: Opens
type: integer
clicks:
default: 0
description: The number of unique link clicks recorded.
title: Clicks
type: integer
temporary_failures:
default: 0
description: The number of temporary delivery failures (e.g. soft bounces).
title: Temporary Failures
type: integer
permanent_failures:
default: 0
description: The number of permanent delivery failures (e.g. hard bounces).
title: Permanent Failures
type: integer
unsubscriptions:
default: 0
description: The number of subscribers who unsubscribed after receiving this email.
title: Unsubscriptions
type: integer
complaints:
default: 0
description: The number of spam complaints recorded against this email.
title: Complaints
type: integer
survey_responses:
default: 0
description: The number of survey responses submitted from this email.
title: Survey Responses
type: integer
webmentions:
default: 0
description: The number of inbound webmentions received for this email.
title: Webmentions
type: integer
page_views_lifetime:
default: 0
description: The total number of archive page views for this email since publication.
tit
# --- truncated at 32 KB (52 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/buttondown/refs/heads/main/openapi/buttondown-external-feeds-api-openapi.yml