# Buttondown

> Run your Buttondown newsletter from a workflow: add, find, update and remove subscribers, draft emails, send or schedule them, and send yourself a test copy first. Every step works on Buttondown's free plan.

App · Email Marketing · 12 actions. Web page: https://docs.lodol.com/docs/integrations/buttondown

## Actions

### Add subscriber

Put someone on your Buttondown list, with any notes and custom fields you want to keep on them. Fails if the address is already subscribed.

**Inputs**

- Email address (`email_address`, text, required): The address to subscribe.
- Notes (`notes`, text): A private note about this subscriber. Only you see it.
- Custom fields (`metadata`, object): Your own data to store on the subscriber, as an object, for example {"plan": "pro", "signed_up_from": "pricing page"}. Available in emails as template variables.
- Signed up from (`referrer_url`, text): The page they subscribed from, if you want to record it.

**Outputs**

- `click_rate` (number)
- `email_address` (text)
- `emails_clicked` (number)
- `emails_delivered` (number)
- `emails_opened` (number)
- `id` (text)
- `last_clicked_on` (text)
- `last_opened_on` (text)
- `metadata` (object)
- `notes` (text)
- `open_rate` (number)
- `referral_code` (text)
- `source` (text)
- `status` (text)
- `subscribed_on` (text)
- `tags` (list)
- `unsubscribed_on` (text)

**Example output**

```json
{
  "click_rate": 0.25,
  "email_address": "ada@example.com",
  "emails_clicked": 3,
  "emails_delivered": 12,
  "emails_opened": 9,
  "id": "sub_01h8xg4j3k2m1n0p9q8r7s6t5v",
  "last_clicked_on": null,
  "last_opened_on": "2026-09-12T08:30:00Z",
  "metadata": {
    "plan": "pro"
  },
  "notes": "Signed up from the pricing page.",
  "open_rate": 0.75,
  "referral_code": "ada-9f2c",
  "source": "api",
  "status": "regular",
  "subscribed_on": "2026-09-01T10:04:00Z",
  "tags": [],
  "unsubscribed_on": null
}
```

### Delete an email

Remove an email from Buttondown. Use it to drop a draft you no longer want, or to call off a scheduled send before it goes.

**Inputs**

- Email to delete (`email_id`, text, required): Pick one of your emails, or use the one an earlier 'Draft an email' step created.

**Outputs**

- `deleted` (true/false)
- `email_id` (text)

**Example output**

```json
{
  "deleted": true,
  "email_id": "em_01h8xg4j3k2m1n0p9q8r7s6t5v"
}
```

### Delete subscriber

Erase a subscriber and everything Buttondown recorded about them. This cannot be undone; to simply stop emailing someone, set their status to Unsubscribed instead.

**Inputs**

- Subscriber (`subscriber`, text, required): The subscriber's email address, or their Buttondown ID.

**Outputs**

- `deleted` (true/false)
- `subscriber` (text)

**Example output**

```json
{
  "deleted": true,
  "subscriber": "ada@example.com"
}
```

### Draft an email

Write a new email and leave it as a draft. Nothing is sent: use 'Send an email' or 'Schedule an email' when it's ready, or open it in Buttondown to finish it by hand.

**Inputs**

- Subject (`subject`, text, required): The subject line.
- Body (`body`, text, required): What the email says. Markdown works: **bold**, [links](https://example.com), lists and headings.
- Archive description (`description`, text): A one-line summary shown on the email's public archive page and in search results.
- Archive link (`slug`, text): The last part of the email's archive URL. Leave blank and Buttondown makes one from the subject.
- Original post URL (`canonical_url`, text): If this email republishes something already on the web, the address it came from.

**Outputs**

- `archive_url` (text)
- `body` (text)
- `canonical_url` (text)
- `created_on` (text)
- `description` (text)
- `id` (text)
- `publish_date` (text)
- `slug` (text)
- `status` (text)
- `subject` (text)

**Example output**

```json
{
  "archive_url": "https://buttondown.com/example/archive/what-we-shipped-in-september/",
  "body": "Hello! Here is what changed this month.",
  "canonical_url": "",
  "created_on": "2026-09-15T16:20:00Z",
  "description": "September's release notes.",
  "id": "em_01h8xg4j3k2m1n0p9q8r7s6t5v",
  "publish_date": null,
  "slug": "what-we-shipped-in-september",
  "status": "draft",
  "subject": "What we shipped in September"
}
```

### Find subscriber

Look someone up by email address or ID and get their status and engagement. If they're not on the list the step says so and carries on, rather than failing the workflow.

**Inputs**

- Subscriber (`subscriber`, text, required): The subscriber's email address, or their Buttondown ID.

**Outputs**

- `found` (true/false)
- `subscriber` (object)

**Example output**

```json
{
  "found": true,
  "subscriber": {
    "click_rate": 0.25,
    "email_address": "ada@example.com",
    "emails_clicked": 3,
    "emails_delivered": 12,
    "emails_opened": 9,
    "id": "sub_01h8xg4j3k2m1n0p9q8r7s6t5v",
    "last_clicked_on": null,
    "last_opened_on": "2026-09-12T08:30:00Z",
    "metadata": {
      "plan": "pro"
    },
    "notes": "Signed up from the pricing page.",
    "open_rate": 0.75,
    "referral_code": "ada-9f2c",
    "source": "api",
    "status": "regular",
    "subscribed_on": "2026-09-01T10:04:00Z",
    "tags": [],
    "unsubscribed_on": null
  }
}
```

### Get an email

Read one email: its subject, body, status, archive link and when it goes out or went out.

**Inputs**

- Email to read (`email_id`, text, required): Pick one of your emails, or use the one an earlier 'Draft an email' step created.

**Outputs**

- `archive_url` (text)
- `body` (text)
- `canonical_url` (text)
- `created_on` (text)
- `description` (text)
- `id` (text)
- `publish_date` (text)
- `slug` (text)
- `status` (text)
- `subject` (text)

**Example output**

```json
{
  "archive_url": "https://buttondown.com/example/archive/what-we-shipped-in-september/",
  "body": "Hello! Here is what changed this month.",
  "canonical_url": "",
  "created_on": "2026-09-15T16:20:00Z",
  "description": "September's release notes.",
  "id": "em_01h8xg4j3k2m1n0p9q8r7s6t5v",
  "publish_date": null,
  "slug": "what-we-shipped-in-september",
  "status": "draft",
  "subject": "What we shipped in September"
}
```

### List emails

Read your emails, newest first: drafts, scheduled and sent. Narrow them by status, by words in the subject, or by when they were published.

**Inputs**

- Status (`statuses`, list): Only emails in these states. Leave blank for all of them. One or more of: `draft`, `scheduled`, `about_to_send` (About to send), `in_flight` (Sending now), `sent`, `paused`, `errored`, `imported`.
- Subject contains (`subject_contains`, text): Only emails whose subject contains this text.
- Published on or after (`published_after`, date): Only emails published on or after this day.
- Published on or before (`published_before`, date): Only emails published on or before this day.
- Sort by (`ordering`, text): The order to read them in. One of: `-creation_date` (Most recently created first), `creation_date` (Oldest created first), `-publish_date` (Most recently published first), `publish_date` (Oldest published first), `subject` (By subject, A to Z). Default: `-creation_date`.
- Page (`page`, number): Which page of emails to read. Starts at 1; the result says whether there are more. At least 1.

**Outputs**

- `count` (number)
- `emails` (list)
- `has_more` (true/false)
- `page` (number)

**Example output**

```json
{
  "count": 1,
  "emails": [
    {
      "archive_url": "https://buttondown.com/example/archive/what-we-shipped-in-september/",
      "body": "Hello! Here is what changed this month.",
      "canonical_url": "",
      "created_on": "2026-09-15T16:20:00Z",
      "description": "September's release notes.",
      "id": "em_01h8xg4j3k2m1n0p9q8r7s6t5v",
      "publish_date": null,
      "slug": "what-we-shipped-in-september",
      "status": "draft",
      "subject": "What we shipped in September"
    }
  ],
  "has_more": false,
  "page": 1
}
```

### List subscribers

Read your subscribers, newest first, and how many there are. Narrow them by status, by part of an email address, or by when they joined.

**Inputs**

- Status (`statuses`, list): Only subscribers in these states. Leave blank for all of them. One or more of: `regular` (Subscribed), `unactivated` (Not confirmed yet), `unsubscribed`, `undeliverable`, `complained` (Marked an email as spam), `blocked`, `removed`, `premium` (Paying), `gifted` (Gifted premium access), `trialed` (Trialling premium), and 6 more.
- Email contains (`email_contains`, text): Only subscribers whose address contains this text: a whole address, or a domain like 'example.com'.
- Joined on or after (`subscribed_after`, date): Only subscribers who joined on or after this day.
- Joined on or before (`subscribed_before`, date): Only subscribers who joined on or before this day.
- Sort by (`ordering`, text): The order to read them in. One of: `-creation_date` (Newest first), `creation_date` (Oldest first). Default: `-creation_date`.
- Page (`page`, number): Which page of subscribers to read. Starts at 1; the result says whether there are more. At least 1.

**Outputs**

- `count` (number)
- `has_more` (true/false)
- `page` (number)
- `subscribers` (list)

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "page": 1,
  "subscribers": [
    {
      "click_rate": 0.25,
      "email_address": "ada@example.com",
      "emails_clicked": 3,
      "emails_delivered": 12,
      "emails_opened": 9,
      "id": "sub_01h8xg4j3k2m1n0p9q8r7s6t5v",
      "last_clicked_on": null,
      "last_opened_on": "2026-09-12T08:30:00Z",
      "metadata": {
        "plan": "pro"
      },
      "notes": "Signed up from the pricing page.",
      "open_rate": 0.75,
      "referral_code": "ada-9f2c",
      "source": "api",
      "status": "regular",
      "subscribed_on": "2026-09-01T10:04:00Z",
      "tags": [],
      "unsubscribed_on": null
    }
  ]
}
```

### Schedule an email

Set a draft to go out to everyone on your list at a date and time you choose. Buttondown sends it then, whether or not this workflow is still running.

**Inputs**

- Email to schedule (`email_id`, text, required): Pick one of your emails, or use the one an earlier 'Draft an email' step created.
- Send at (`send_at`, date and time, required): When to send it. Must be in the future.

**Outputs**

- `archive_url` (text)
- `body` (text)
- `canonical_url` (text)
- `created_on` (text)
- `description` (text)
- `id` (text)
- `publish_date` (text)
- `slug` (text)
- `status` (text)
- `subject` (text)

**Example output**

```json
{
  "archive_url": "https://buttondown.com/example/archive/what-we-shipped-in-september/",
  "body": "Hello! Here is what changed this month.",
  "canonical_url": "",
  "created_on": "2026-09-15T16:20:00Z",
  "description": "September's release notes.",
  "id": "em_01h8xg4j3k2m1n0p9q8r7s6t5v",
  "publish_date": "2026-10-01T14:00:00Z",
  "slug": "what-we-shipped-in-september",
  "status": "scheduled",
  "subject": "What we shipped in September"
}
```

### Send a test copy

Send a copy of a draft to the addresses you name, so you can read it before the real send. Your subscribers get nothing.

**Inputs**

- Email to test (`email_id`, text, required): Pick one of your emails, or use the one an earlier 'Draft an email' step created.
- Send the test to (`recipients`, list, required): The addresses that should get the test copy.

**Outputs**

- `email_id` (text)
- `recipients` (list)
- `sent` (true/false)

**Example output**

```json
{
  "email_id": "em_01h8xg4j3k2m1n0p9q8r7s6t5v",
  "recipients": [
    "you@example.com"
  ],
  "sent": true
}
```

### Send an email

Send a draft to everyone on your list, now. Real email goes out and it can't be recalled; send a test copy first if you want to check it.

**Inputs**

- Email to send (`email_id`, text, required): Pick one of your emails, or use the one an earlier 'Draft an email' step created.

**Outputs**

- `archive_url` (text)
- `body` (text)
- `canonical_url` (text)
- `created_on` (text)
- `description` (text)
- `id` (text)
- `publish_date` (text)
- `slug` (text)
- `status` (text)
- `subject` (text)

**Example output**

```json
{
  "archive_url": "https://buttondown.com/example/archive/what-we-shipped-in-september/",
  "body": "Hello! Here is what changed this month.",
  "canonical_url": "",
  "created_on": "2026-09-15T16:20:00Z",
  "description": "September's release notes.",
  "id": "em_01h8xg4j3k2m1n0p9q8r7s6t5v",
  "publish_date": null,
  "slug": "what-we-shipped-in-september",
  "status": "about_to_send",
  "subject": "What we shipped in September"
}
```

### Update subscriber

Change a subscriber's address, status, notes or custom fields. Set the status to Unsubscribed to stop emailing someone while keeping their record.

**Inputs**

- Subscriber (`subscriber`, text, required): The subscriber's email address, or their Buttondown ID.
- New email address (`email_address`, text): Move them to a different address. Leave blank to keep the one they have.
- Status (`status`, text): Whether they should be receiving your newsletter. Leave blank to keep it as it is. One of: `regular` (Subscribed), `unsubscribed`.
- Notes (`notes`, text): A private note about this subscriber, replacing the note they have now.
- Custom fields (`metadata`, object): Your own data to store on the subscriber, as an object, for example {"plan": "pro", "signed_up_from": "pricing page"}. Available in emails as template variables.

**Outputs**

- `click_rate` (number)
- `email_address` (text)
- `emails_clicked` (number)
- `emails_delivered` (number)
- `emails_opened` (number)
- `id` (text)
- `last_clicked_on` (text)
- `last_opened_on` (text)
- `metadata` (object)
- `notes` (text)
- `open_rate` (number)
- `referral_code` (text)
- `source` (text)
- `status` (text)
- `subscribed_on` (text)
- `tags` (list)
- `unsubscribed_on` (text)

**Example output**

```json
{
  "click_rate": 0.25,
  "email_address": "ada@example.com",
  "emails_clicked": 3,
  "emails_delivered": 12,
  "emails_opened": 9,
  "id": "sub_01h8xg4j3k2m1n0p9q8r7s6t5v",
  "last_clicked_on": null,
  "last_opened_on": "2026-09-12T08:30:00Z",
  "metadata": {
    "plan": "pro"
  },
  "notes": "Signed up from the pricing page.",
  "open_rate": 0.75,
  "referral_code": "ada-9f2c",
  "source": "api",
  "status": "regular",
  "subscribed_on": "2026-09-01T10:04:00Z",
  "tags": [],
  "unsubscribed_on": null
}
```
