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

# Accounts

> Model the companies, workspaces and teams your contacts belong to, and message them as one

# Accounts

Accounts are the organizations behind your contacts: the company, workspace or team that a user belongs to in your product. Contacts stay the unit you email; accounts add the layer that B2B products actually bill and support.

With accounts you can:

* keep plan, seats, MRR and trial dates on the organization and use them in every member's segments and emails
* send an event about the organization (trial ending, payment failed, seat limit reached) to the right people in it
* run a sequence once per company instead of once per seat
* see who belongs to which account, with roles, on one page

<Note>
  Accounts are your customers' organizations. They are separate from your
  Sequenzy account (`sequenzy account`, the `get_account` MCP tool and `GET
      /api/v1/account`) and from the `account:read` API key scope. Account endpoints
  use the `subscribers:*` scopes.
</Note>

You manage accounts in the **Accounts** tab under **Subscribers**. Nothing about contacts, events or segments changes until your workspace turns Accounts on.

## Turning Accounts on

Your workspace turns Accounts on when you create its first account (in the dashboard, API, CLI or MCP) or run the backfill. It stays on after that, even if you delete every account.

Accounts use `account.*` names in segments and merge tags. If your contacts already have a custom attribute named `account` or `account.<name>`, Sequenzy refuses to turn Accounts on (the API returns `409`) and the Accounts tab lists the attributes to rename. Without this check, segments built on those attributes would stop updating.

## Data model

| Property      | Type   | Description                                                                 |
| ------------- | ------ | --------------------------------------------------------------------------- |
| `externalId`  | string | Your organization ID. Required, unique per workspace, case-sensitive.       |
| `name`        | string | Display name.                                                               |
| `domain`      | string | Primary domain, normalized to a hostname such as `acme.com`.                |
| `attributes`  | object | Up to 100 custom attributes: plan, seats, mrr, trialEndsAt, usage counters. |
| `memberCount` | number | Maintained by Sequenzy.                                                     |
| `lastEventAt` | date   | Time of the latest account event.                                           |

Members are contacts with a role: `owner`, `admin` or `member`. A contact can belong to several accounts.

## Getting started

<Steps>
  <Step title="Use what you already send">
    If your events carry an organization id (for example `workspaceId`, `organizationId` or `teamId`), or your contacts carry one as an attribute (for example `account_id` with a `company_name` next to it), open **Subscribers**, then **Accounts**. Sequenzy shows the property it found and previews the biggest organizations it would create, with their contacts. Accounts are named from a matching name property (such as `workspaceName`) or, when there is none, after the work email domain most of their contacts share, so an ID like `zplgap...` with contacts at `leadpages.com` becomes **Leadpages**. Creating them adds each contact to their organization's account in the background. Nothing is sent, and no sequences or sync rules run. The same flow is available from the [API](/api-reference/accounts/organization-ids-detect), `sequenzy accounts detect-org-ids` and the `detect_account_organization_ids` MCP tool.
  </Step>

  <Step title="Or accept suggestions from email domains">
    No organization id? When several contacts share a work email domain, such as seven people at `acme.com`, **Subscribers**, then **Accounts** suggests an account for it. Uncheck any that are not customers and create the rest. Each becomes an account named after the company (external ID and domain `acme.com`), and the domain's contacts become members. Hover a contact count to see who is behind it. Nothing is sent and no sequences start.

    Personal and disposable providers (such as `gmail.com` or `yopmail.com`), your own sending domains, domains where a contact already belongs to an account (for example through an organization ID sync) and domains an account already uses are never suggested. The same suggestions are available from the [API](/api-reference/accounts/suggestions-list), `sequenzy accounts suggestions` and the `list_account_suggestions` MCP tool.
  </Step>

  <Step title="Or sync from your app">
    Upsert the account, add members, and send account events. The same three calls exist in the CLI, MCP tools, and the SDKs.

    ```bash theme={null}
    curl -X POST "https://api.sequenzy.com/api/v1/accounts" \
      -H "Authorization: Bearer API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"externalId": "org_123", "name": "Acme", "domain": "acme.com",
           "attributes": {"plan": "pro", "seats": 5, "trialEndsAt": "2026-09-20"}}'

    curl -X POST "https://api.sequenzy.com/api/v1/accounts/org_123/members" \
      -H "Authorization: Bearer API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"email": "jane@acme.com", "role": "owner"}'
    ```
  </Step>

  <Step title="Attach contacts from their events">
    Once Accounts is on, any contact event can carry an `account` reference. The account is created if it does not exist and the contact becomes a member. Before Accounts is on, `account` is ignored exactly as it was before this feature existed, and the response includes `accountIgnored` so you can tell.

    ```bash theme={null}
    curl -X POST "https://api.sequenzy.com/api/v1/subscribers/events" \
      -H "Authorization: Bearer API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"email": "jane@acme.com", "event": "project_created", "account": "org_123"}'
    ```

    Pass an object instead of a string to set the role or name at the same time: `{"externalId": "org_123", "name": "Acme", "role": "owner"}`.

    In the CLI, use `sequenzy subscribers event jane@acme.com --name project_created --account org_123`, or replace `--account` with `--account-json '{"externalId":"org_123","role":"owner"}'` for profile fields and a role. The MCP `trigger_subscriber_event` tool accepts the same string or object in `account`. These options also work with historical events; the timestamp determines whether sequences run.
  </Step>
</Steps>

## Attributes in segments and emails

Account attributes fan out to every member as `account.<name>`. Nothing changes on the contact's own custom attributes; the account values live alongside them.

* **Segments**: filter on `account.plan is pro`, `account.seats greater than 5`, or `account.role is owner` with the existing attribute filter.
* **Merge tags**: `{{account.name}}`, `{{account.domain}}`, `{{account.externalId}}`, `{{account.memberCount}}`, `{{account.role}}` and `{{account.<attribute>}}` work in campaigns, sequences and previews.
* **Sequence conditions**: see the table below.

| Name                   | Reads                                                    | Use it for                                                              |
| ---------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------- |
| `account.<name>`       | The contact's primary account right now                  | Segments, merge tags, conditions in any sequence                        |
| `event.account.<name>` | The account as it was when the triggering event happened | Sequences started by an account event or a contact event with `account` |

Once Accounts is on, the `account.` namespace is reserved for account data. A contact custom attribute named `account` (or `account.<anything>`) is still saved on the contact profile but is no longer synced for segments, so it cannot shadow or clear account values.

### Contacts in several accounts

Segments, merge tags and `account.<name>` conditions use one **primary** account per contact: the membership with the highest role (owner, then admin, then member), and the oldest membership when roles tie. The account page and the contact's profile show every membership. Account events still reach the contact through each account they belong to.

## Billing from payment integrations

If Stripe, Paddle, Lemon Squeezy or another payment integration is connected, accounts show the company's billing without any setup. After each payment event or revenue sync, Sequenzy files the paying contact under their account and updates these account attributes:

| Attribute          | Value                                                                  |
| ------------------ | ---------------------------------------------------------------------- |
| `plan`             | Plan name, or plan ID when there is no name                            |
| `mrr`              | Sum of the members' MRR                                                |
| `billing_status`   | `active`, `trialing`, `past_due`, `cancelled` or `churned`, best first |
| `billing_interval` | Billing interval of that subscription                                  |
| `trial_ends_at`    | Trial end, while trialing                                              |
| `customer_since`   | When the first paying member was added as a contact                    |
| `ltv`              | Sum of the members' lifetime revenue, including one-time purchases     |

The paying contact joins the account they already belong to, otherwise the one account using their work email domain, otherwise the account whose ID matches an organization ID on the contact (for example Stripe customer metadata `workspaceId`). A contact counts as paying with a payment tag, MRR or lifetime revenue, so one-time buyers are included. They become Owner when the account has none. Like other account attributes, these reach every member as `account.plan`, `account.billing_status` and so on, so a segment on `account.billing_status` includes teammates who never paid. When a workspace turns Accounts on, existing paying customers are filed and rolled up automatically.

## Account events

An account event is about the organization, not one person. Sequenzy records it on the account timeline and delivers it to the chosen recipients as a normal contact event, so sync rules and sequence triggers run per person.

By default only **owners** receive it. Pass `recipients: "all"` when every member should get the email.

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/accounts/org_123/events" \
  -H "Authorization: Bearer API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": "trial_ending", "properties": {"daysLeft": 3}, "recipients": "owners"}'
```

| `recipients` | Who receives the contact event                                       |
| ------------ | -------------------------------------------------------------------- |
| `owners`     | Default. Owners; falls back to admins when the account has no owner. |
| `admins`     | Owners and admins.                                                   |
| `all`        | Every member.                                                        |
| `none`       | Nobody. The event is recorded on the timeline only.                  |

Each delivery carries `event.account.externalId`, `event.account.name`, `event.account.role` and the account attributes, so a sequence triggered by `trial_ending` can say "Acme's trial ends in `{{event.daysLeft}}` days".

Pass `occurredAt` (ISO 8601) to preserve an event’s original timestamp, or omit it for the current time. This is also available as CLI `--occurred-at` and MCP `trigger_account_event.occurredAt`.

Pass `eventId` when your integration may retry. The ID is scoped to the account, so two accounts can use the same ID even when they share members. Retries keep the original recipients and event data, skip completed deliveries, and resume failed work without duplicating sequence enrollments.

## Once per account

Set the sequence's enrollment mode to **matching field** with `account.externalId` to allow one active run per organization across its members. Combined with `recipients: owners`, only one owner enrolls while that account's run is active. A new event can start another run after it finishes; other matching fields retain their per-contact behavior.

## Limits and behavior

* 100 attributes per account; attribute keys up to 100 characters; string values up to 2,000 characters.
* Attribute fan-out and recipient resolution cover up to 5,000 members per account.
* Deleting an account keeps the contacts and clears their `account.*` values. Deleting a contact removes their memberships. If attribute cleanup is temporarily unavailable, Sequenzy retries it automatically.
* Account events are kept for the same retention window as contact events.

## API, CLI and MCP

* REST: [List](/api-reference/accounts/list), [Upsert](/api-reference/accounts/upsert), [Get](/api-reference/accounts/get), [Update](/api-reference/accounts/update), [Delete](/api-reference/accounts/delete), [Members](/api-reference/accounts/members), [Trigger event](/api-reference/accounts/events-trigger), [List events](/api-reference/accounts/events-list).
* CLI: `sequenzy accounts list|get|upsert|delete|members|add-member|remove-member|event|events`. See the [CLI reference](/concepts/cli#accounts).
* MCP: `list_accounts`, `get_account_by_external_id`, `upsert_account`, `delete_account`, `list_account_members`, `add_account_member`, `remove_account_member`, `trigger_account_event`, `list_account_events`. See the [MCP reference](/concepts/mcp).
