---
title: "Organization & Team"
description: "Organization settings, branches, departments and projects, team members, roles and per-member access overrides."
url: "https://bareledger.app/guides/api-tenancy"
category: "Developers & API"
updated: "2026-11-06"
publisher: "BareLedger (Syneria Technologies OPC)"
---

# Organization & Team

> Organization settings, branches, departments and projects, team members, roles and per-member access overrides.

All routes tenant-scoped unless noted: each request acts on the one organization named in `X-Tenant`, which must be one of the caller's own registered organizations. Nothing here lists or reaches other tenants.

## Tenant settings

| Method & Path | Permission | Purpose | Side effects |
|---|---|---|---|
| `GET tenant` | — | Active tenant profile + effective permissions | — |
| `PATCH tenant` | `tenant.manage` (+`tenant.security.manage` for MFA-policy fields) | Update org profile | **202** — opens an email-OTP change request, not applied immediately |
| `GET tenant/numbering-settings` | `tenant.view` | Effective per-doc-type numbering prefix/padding | — |
| `PUT tenant/numbering-settings` | `tenant.manage` | Update numbering prefixes/padding | Rejects if the series already issued numbers; audit |
| `GET tenant/collection-settings` | `tenant.view` | WHT recognition mode, receipt issuance, payment methods | — |
| `PUT tenant/collection-settings` | `tenant.manage` | Update collection settings | Locks `wht_recognition` once the WHT control account has ledger activity; audit |
| `POST tenant/logo` | `tenant.manage` | Upload org logo | Stores file, deletes prior, audit |
| `GET tenant/tax-pack` | `tenant.manage` | Preview effect of applying a country tax pack | — |
| `POST tenant/tax-pack/apply` | `tenant.manage` | Apply country tax pack | Creates/updates tenant tax rates |
| `GET tenant/tax-registrations` | `tenant.view` | Tax registration profile per tax type | — |
| `PUT tenant/tax-registrations` | `tenant.manage` | Upsert one tax type's registration | Drives which statutory forms apply; audit |

## Change requests (email-OTP confirmation)

| Method & Path | Permission | Purpose |
|---|---|---|
| `POST change-requests/{changeRequest}/confirm` | matches the underlying resource (`tenant.manage`/`branch.manage`/`period.manage`) | Confirm a pending OTP-gated change with the emailed code |

## Branches

| Method & Path | Permission | Purpose | Side effects |
|---|---|---|---|
| `GET branches` | `branch.view` | List branches | — |
| `POST branches` | `branch.manage` | Create branch | No plan cap (branches are unlimited); **202** change request |
| `PATCH branches/{branch}` | `branch.manage` | Update branch | Never plan-capped; **202** change request |

## Departments / Cost Centers / Projects (`feature:dimensions`)

Same CRUD shape (`GET`/`POST`/`PATCH`) for `departments`, `cost-centers`, `projects` — permission `org.view`/`org.manage`, each write audited.

## Members & Access (RBAC)

| Method & Path | Permission | Purpose | Side effects |
|---|---|---|---|
| `GET people` | `member.view` or `employees.view` | The People directory: every login once, joined to its employee record (sign-in status, roles, employee status; "No sign-in" for legacy employees without a login) | — |
| `GET members` | `member.view` | List tenant members | — |
| `POST members` | `member.invite` | Invite a member by email + roles (any combination)/permissions | Seat-capacity (402 `plan_limit_reached`; every active sign-in is a seat) + privilege-ceiling checks; creates user if new; sends invite email; audit `member.invited` |
| `POST members/{membership}/resend-invite` | `member.invite` | Resend invitation | New token, sends email, audit |
| `PATCH members/{membership}/roles` | `member.manage` | Replace the member's role set (a checklist) | Privilege-ceiling + self-lockout guards; refuses adding `employee` without an employee record or removing it while employed (422); clears overrides; audit |
| `PATCH members/{membership}/permissions` | `member.manage` + `feature:advanced_rbac` | Set per-member permission overrides | Privilege-ceiling + self-lockout guards; audit |
| `POST members/{membership}/reactivate` | `member.manage` | Reactivate a suspended member | Re-checks seat cap (402 `plan_limit_reached`); audit |
| `POST members/{membership}/transfer-ownership` | owner-only + password confirm | Transfer tenant ownership | Old owner keeps Administrator role; audit |
| `DELETE members/{membership}` | `member.manage` | Remove member access (suspend) | Audit |

## Seat checks on employee routes

Every active sign-in is a `users` seat, employee-only included. These return **402 `plan_limit_reached`** at the plan's user limit: `POST employee-onboardings/{onboarding}/approve` (only when approval creates a new login; an email that is already a member just gains the `employee` role), `POST employees/{employee}/reactivate` and `POST employees/{employee}/invite-login`. A sign-in that is beyond the limit after the 14-day grace gets **402 `seat_over_limit`** on any write (reads, billing, support, notifications and profile stay open).

## Employees — tax profile

Effective-dated windows the statutory calculator reads on the pay date (the API; see [Employees & Onboarding](https://bareledger.app/guides/employees-onboarding)). All values are encrypted at rest.

| Method & Path | Permission | Purpose | Side effects |
|---|---|---|---|
| `GET employees/{employee}/tax-profile` | `employees.view` | `current` window, full `history`, `options` (`country`, `tax_statuses` from the pack's `tax_status_options` rule when it defines one — PH BIR codes — and `fields` saying which inputs the country uses: `tax_status`, `minimum_wage_earner`, `substituted_filing`, `tax_code`), `can_edit` | Without `employees.manage` the status, previous-employer figures and `extra.tax_code` are masked (`••••1234`) |
| `PUT employees/{employee}/tax-profile` | `employees.manage` | Upsert the window starting on `effective_from` (`YYYY-MM-DD`, required): edits in place if one starts that day, else adds it and closes the earlier open-ended window the day before. Body: `effective_to` (≥ from), `tax_status` (must be in the country list when one exists), `minimum_wage_earner`, `substituted_filing`, `prev_employer_gross_ytd` / `prev_employer_tax_ytd` (≥ 0 — P45 / BIR 2316 figures from an earlier employer in the same tax year), `extra.tax_code` (UK PAYE code, read by the calculator when the registration has none) | 422 `employee` on one's own record (same rule as the other employee writes); audit `employee.tax_profile_updated` with before/after, sensitive values masked |

## Reference/meta data

| Method & Path | Permission | Purpose |
|---|---|---|
| `GET meta/permissions` | `member.view` | Permission catalogue for admin UI |
| `GET meta/tiers` | `member.view` | Module access-tier matrix + role presets |
| `GET meta/roles` | `member.view` | Roles in active tenant |
| `GET meta/tax-rates` | — | Active tax rates (form dropdowns) |
| `GET meta/country-catalogs` | — | Country-specific code catalogues |
| `GET meta/account-subtypes` | `coa.view` | Suggested account subtypes |
