> ## 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.

# Create or Update Account

> Upsert an account by your own organization ID

# Create or Update Account

Creates the account when `externalId` is new, otherwise updates it. Attributes merge into the stored attributes: send `null` to delete a key, or `replaceAttributes: true` to replace them all. Attribute changes fan out to every member for segments and `{{account.*}}` merge tags.

Your first account turns Accounts on for the workspace. If your contacts already carry a custom attribute named `account` or `account.<name>`, this returns `409` until you rename it, because account data takes over the `account.*` names in segments.

## Request

<ParamField body="externalId" type="string" required>
  Your organization ID. Case-sensitive, unique per workspace, up to 255
  characters.
</ParamField>

<ParamField body="name" type="string">
  Display name. `null` clears it.
</ParamField>

<ParamField body="domain" type="string">
  Primary domain, normalized to a hostname (`https://www.acme.com/` becomes
  `acme.com`). `null` clears it.
</ParamField>

<ParamField body="attributes" type="object">
  Up to 100 attributes such as `plan`, `seats`, `mrr`, `trialEndsAt`. Values may
  be strings, numbers, booleans, arrays of those, or nested objects (flattened
  to dotted names). Keys starting with `internal__` are reserved.
</ParamField>

<ParamField body="replaceAttributes" type="boolean" default="false">
  Replace all stored attributes instead of merging.
</ParamField>

<ParamField body="members" type="array">
  Up to 100 contacts to add in the same call. Each item takes `email` or
  `externalId`, an optional `role` (`owner`, `admin`, `member`), `firstName` and
  `lastName`. New emails create the contact; external-ID-only members must
  already exist. Member roles and identities are checked before changing the
  account or adding contacts.
</ParamField>

```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" },
    "members": [{ "email": "jane@acme.com", "role": "owner" }]
  }'
```

## Responses

<ResponseExample>
  ```json 201 theme={null}
  {
    "success": true,
    "created": true,
    "account": {
      "id": "acc_abc123",
      "externalId": "org_123",
      "name": "Acme",
      "domain": "acme.com",
      "attributes": { "plan": "pro", "seats": 5, "trialEndsAt": "2026-09-20" },
      "memberCount": 1,
      "lastEventAt": null,
      "createdAt": "2026-09-04T09:00:00.000Z",
      "updatedAt": "2026-09-04T09:00:00.000Z"
    },
    "members": [
      { "subscriberId": "sub_1", "email": "jane@acme.com", "externalId": null, "role": "owner", "created": true }
    ]
  }
  ```

  ```json 200 theme={null}
  {
    "success": true,
    "created": false,
    "account": {
      "id": "acc_abc123",
      "externalId": "org_123",
      "attributes": { "plan": "pro" }
    }
  }
  ```

  ```json 400 theme={null}
  {
    "success": false,
    "error": "Account `domain` must be a hostname such as `acme.com`."
  }
  ```

  ```json 401 theme={null}
  { "success": false, "error": "Unauthorized" }
  ```

  ```json 409 theme={null}
  {
    "success": false,
    "error": "Contacts in this workspace already use the custom attribute `account.plan`. Accounts reserve the `account` attribute name for organization data, so turning Accounts on would stop those contact attributes from updating in segments. Rename them (for example to `company.plan`), then try again."
  }
  ```
</ResponseExample>
