> ## Documentation Index
> Fetch the complete documentation index at: https://docs.subscriber.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscribers

> The people you email: their details, tags, and whether they've opted in.

A subscriber is someone you email, usually one of your users. Workflows and broadcasts always send to subscribers, so anyone you want to email needs to be one first.

Subscribers belong to an environment, so production and staging each have their own.

## What a subscriber has

| Field | Description |
| - | - |
| `email` | Where emails go. A subscriber without one is skipped. |
| `externalId` | Your own ID for them, such as the user ID in your database. Use it to find them without storing ours. |
| `publicId` | Subscriber.dev's ID for them. Generated for you, or set your own when you create them. |
| `firstName`, `lastName`, `name` | Their name, for [templates](https://docs.subscriber.dev/templates.md). |
| `phone` | Stored for your reference. |
| `attributes` | Anything else you want to use in emails or audiences, such as `{"plan": "pro", "company": "Acme"}`. |

You need at least one of `email`, `externalId` or `publicId` to find a subscriber again. Anywhere that takes a subscriber, such as triggering a workflow, accepts any of the three.

## Add and update subscribers

Or ask [your agent](https://docs.subscriber.dev/mcp.md): "Add [jane@acme.com](mailto:jane@acme.com), first name Jane, plan pro."

> [tab] CLI
>
> ```bash theme={null}
> subscriber subscribers create --email jane@acme.com --first-name Jane --external-id user_123 \
>   --attributes '{"plan": "pro"}'
> subscriber subscribers update <subscriberId> --last-name Doe
> subscriber subscribers list --search acme
> ```
>
> `--attributes` on `update` replaces all of a subscriber's attributes, so include the ones you want to keep.

> [tab] TUI
>
> Open **Subscribers** and press `n` to add someone. Choose a subscriber and press `e` to edit them.

> [tab] API
>
> ```bash theme={null}
> curl -X POST https://api.subscriber.dev/subscribers \
>   -H "x-api-key: $KEY" -H "content-type: application/json" \
>   -d '{"email": "jane@acme.com", "firstName": "Jane", "externalId": "user_123", "attributes": {"plan": "pro"}}'
> ```
>
> Update with `PATCH /subscribers/$SUBSCRIBER`. Only the fields you send change.

Creating a subscriber that already exists fails. To create or update in one go, use bulk import.

Subscribers can also be added for you: a [Stripe trigger](https://docs.subscriber.dev/integrations/stripe.md) adds the customer if they aren't a subscriber yet.

## Import subscribers

Bulk import creates new subscribers and updates existing ones, up to 500 per request. Each row is matched by `publicId`, then `externalId`, then `email`; if nothing matches, it's created. One bad row doesn't stop the rest.

```json subscribers.json theme={null}
[
  { "email": "jane@acme.com", "firstName": "Jane", "attributes": { "plan": "pro" } },
  { "email": "sam@acme.com", "externalId": "user_456" }
]
```

> [tab] CLI
>
> ```bash theme={null}
> subscriber subscribers bulk --file subscribers.json
> ```
>
> The file can be a bare array or `{"subscribers": [...]}`. Use `--file -` to read from stdin.

> [tab] API
>
> ```bash theme={null}
> curl -X POST https://api.subscriber.dev/subscribers/bulk \
>   -H "x-api-key: $KEY" -H "content-type: application/json" \
>   -d '{"subscribers": [{"email": "jane@acme.com", "firstName": "Jane"}]}'
> ```
>
> The response has a result for each row (`created`, `updated` or `error`) and a summary count.

For more than 500, split the list into batches. Your agent can do this for you: give it a CSV export and ask it to import it.

## Tags

Tags are labels, such as `beta` or `vip`, that you use to pick who gets a [broadcast](https://docs.subscriber.dev/broadcasts.md#audiences).

> [tab] CLI
>
> ```bash theme={null}
> subscriber subscribers tag <subscriberId> --add beta
> subscriber subscribers tag <subscriberId> --remove beta
> ```

> [tab] TUI
>
> Choose a subscriber and press `t`.

> [tab] API
>
> ```bash theme={null}
> curl -X POST https://api.subscriber.dev/subscribers/$SUBSCRIBER/tags \
>   -H "x-api-key: $KEY" -H "content-type: application/json" \
>   -d '{"tag": "beta"}'
> ```
>
> Remove one with `DELETE .../tags/beta`. `GET /subscribers/tags` lists every tag in use.

## Opting in and out

Each subscriber is either opted in to email or opted out. New subscribers are opted in unless you say otherwise. Opted-out subscribers are never emailed: their email steps are skipped, and webhook steps still run.

People opt out when they:

* click the unsubscribe link in any email,
* use their email client's unsubscribe button, or
* hard bounce, meaning their address doesn't exist. See [Bounces](https://docs.subscriber.dev/sending.md#bounces).

You can also change it yourself, for example to respect an opt-out from your own app:

> [tab] CLI
>
> ```bash theme={null}
> subscriber subscribers update-preferences <subscriberId> --opted-out
> subscriber subscribers list --opted-out
> ```

> [tab] TUI
>
> Choose a subscriber and press `p`.

> [tab] API
>
> ```bash theme={null}
> curl -X PATCH https://api.subscriber.dev/subscribers/$SUBSCRIBER/preferences \
>   -H "x-api-key: $KEY" -H "content-type: application/json" \
>   -d '{"email": false}'
> ```

Every change is kept as a new record, so you have a history of when someone opted in or out.

## Delete a subscriber

Deleting removes the subscriber from lists and audiences, and any emails still waiting to send to them are skipped. The record is kept, not erased.

Use `subscriber subscribers delete <subscriberId>`, or press `d` on a subscriber in the TUI.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.