<aside> <img src="notion://custom_emoji/492827db-2338-4c87-a34e-b0791a3f29d8/30a81003-6f9d-80c2-bec5-007ad1fa0e67" alt="notion://custom_emoji/492827db-2338-4c87-a34e-b0791a3f29d8/30a81003-6f9d-80c2-bec5-007ad1fa0e67" width="40px" />

This is a publicly shared, world-visible document.

</aside>

Why this exists

Plain has merged companies and tenants into one model, now called accounts. An account is the same record as a tenant, with the same ID (te_…). Every tenant field and operation has an account equivalent, and every company operation maps onto one.

What this means for your code:

This guide is for developers updating integrations. For the product-side migration (hiding companies, updating views, workflows, roles and help center settings in the app) see the help center article: Migrating companies to tenants.


TLDR

Company Tenant Account (use this)
companies / searchCompanies tenants / searchTenants accounts / searchAccounts
company(companyId:) tenant(tenantId:) account(accountId:)
upsertCompany createTenant / upsertTenant createAccount / upsertAccount
deleteCompany deleteTenant deleteAccount
updateCustomerCompany addCustomerToTenants / removeCustomerFromTenants / setCustomerTenants addCustomerToAccounts / removeCustomerFromAccounts / setCustomerAccounts
updateCompanyTier updateTenantTier updateAccountTier
— updateThreadTenant updateThreadAccount
Customer.company Customer.tenantMemberships Customer.accountMemberships
— Thread.tenant Thread.account
CompanyIdentifierInput { companyId, companyDomainName } TenantIdentifierInput { tenantId, externalId } AccountIdentifierInput { accountId, externalId }
contractValue, accountOwner tenant fields account fields contract_value, account_owner

Key changes

  1. Everything is an account now. Rename tenant → account (and Tenant → Account) across queries, mutations, inputs, filters and enums. Behaviour is identical.
  2. Companies don't exist once hidden. In a workspace that has hidden companies, every company becomes an account. The ID changes: reads return the account ID (te_…), not the old company ID. The account gets a new Plain-generated externalId (tei_…), so map stored company IDs before you switch (section 10).
  3. Identify accounts by ID or externalId, not domain. AccountIdentifierInput has no domain name option. Look an account up with accounts and the filter property if you only have a domain.
  4. A customer can belong to many accounts. Customer.company (one) becomes Customer.accountMemberships (a paginated list).
  5. Contract value and account owner are account fields. They are no longer first-class properties. Contract value is now in whole currency units, not cents.
  6. Don't send both forms. Sending a tenant field and its account equivalent in the same input (e.g. tenantIdentifiers and accountIdentifiers) fails with BAD_USER_INPUT.
  7. Permissions are renamed. tenant:* becomes account:* (section 10). Both spellings are accepted when creating API keys.