Employees
Adding, changing, and removing employees, and reading your own membership.
An employee links a customer to a company with a role. The role rules are in Companies and roles.
Employee status
| Status | Meaning |
|---|---|
active | A member. Gets the permissions of their role. |
invited | Counts as in the company, but has no permissions. |
removed | No longer a member. The row stays so order history keeps it. |
Lists leave out removed employees unless you filter for them with status.
Adding employees
Merchants add an existing customer with POST /admin/companies/{id}/employees, sending customer_id and an optional role.
- Without a
role, the employee gets the company'scompany.default_roleoverride, else the tenant setting (defaultbuyer). - The customer joins the company's customer group, so its prices apply.
- A customer already in a company fails with
already_in_company.
Buyers can't add employees yet. The company's first owner comes from signup.
Changing roles and removing
The checks run in this order:
- Self-change: buyers can't change their own role or remove themselves (
self_modification). - Owner only: only an owner can give or take
owner, or remove an owner (owner_required). - Last owner: a change can't leave the company without an active owner (
last_owner).
Merchants skip the first two checks, but not the last. Store writes also need an active company. Two changes to the same company's employees run one at a time, so two owners can't remove each other at once. With more than one backend instance this needs Redis (REDIS_URL), which registers a shared lock.
Removing an employee takes the customer out of the company's customer group. The customer account stays, and they can join another company. A role change doesn't touch the group.
If a customer account is deleted, its employee is set to removed. When that was the last owner, the company has no owner until a merchant assigns one.
Your own membership
GET /store/companies/me/membership returns the caller's company ID, employee ID, role, status, company status, and effective permissions. It returns { "membership": null } when the caller has no company.
curl http://localhost:9000/store/companies/me/membership \
-H "x-publishable-api-key: pk_..." \
-H "Authorization: Bearer <customer token>"Use permissions to decide which actions to show. The backend checks every call regardless.
Merchants can look up a customer's company with GET /admin/customers/{id}/company.