# Businesses

### Create a business: `POST /businesses`

One per end user, at their onboarding. `taxId` is their real 9-digit ע.מ/ת.ז, **checksum-validated**, so collect it carefully.

```bash
curl -X POST "$BASE/businesses" -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d '{
  "name": "סטודיו איפור נועה",
  "taxId": "123456782",
  "dealerType": "patur",
  "address": { "street": "הרצל", "house": "12", "city": "תל אביב", "zip": "6688312" },
  "phone": "0501234567",
  "email": "noa@example.com"
}'
```

| Field | Required | Notes |
|---|---|---|
| `name` | ✓ | Registered business name (appears on documents) |
| `taxId` | ✓ | 9 digits, Israeli checksum validated |
| `dealerType` | ✓ | `"patur"` \| `"murshe"` \| `"company"` \| `"ngo"` |
| `registrationNumber` | - | ח"פ for companies |
| `address` | - | `{street, house, city, zip}` |
| `phone`, `email` | - | |
| `startNumbers` | - | Numbering continuation for users migrating from another system: `{"320": 1071}` → their first invoice/receipt here is #1071 |

`201 → {"ok":true, "business":{ "id": "...", ... }}`. **Store `business.id`**; every other call needs it. A per-business signing certificate is issued automatically the first time a document PDF is rendered.

### Read / update: `GET /businesses/:bid` · `PATCH /businesses/:bid`

`PATCH` updates profile fields (name, address, contact). `taxId` and `dealerType` are immutable once the business has issued records.

### Account standing: `POST /businesses/:bid/deactivate` · `POST /businesses/:bid/reactivate`

Two separate switches govern what a business may write, and only one of them is yours:

- **`deactivatedAt`** is **your** pause switch on a tenant. `POST /businesses/:bid/deactivate` stops every write on the business (drafts, issuing, expenses, uploads) while its data and every read keep working; `POST /businesses/:bid/reactivate` clears it. Both are idempotent and return the business. Use it when one of your end users leaves or suspends their account with you.
- **`approvalStatus`** is **BillOS's** master switch, and it has three values: `approved` (the ledger is open), `pending` (never approved: a new account still in our queue), and `suspended` (approved once, then shut by us). Businesses created under an API key are `approved` from birth: your key was the approval. In either closed state writes answer `approval_required` (403), and the message distinguishes them; reactivating on your side never overrides it.

Beside them sit the monthly ceilings: `maxDocsPerMonth` and `maxExpensesPerMonth` on the business object (`null` = unlimited). At a ceiling the write answers `limit_reached` (429) until the next calendar month (Asia/Jerusalem). A ceiling can come from the business's **plan** (`planKey`, a named tier) or from an override we set on the account itself; an override always wins, and the numbers on the business object are the ones actually in force.

Every one of these fields rides the business object, so `GET /businesses/:bid` always tells you why a write is being refused, and `business.status_changed` (section 11) pushes the change to you the moment it happens, so your users hear it from you rather than from a 403.

### PDF branding: `PATCH /businesses/:bid` with `branding`

Per-business styling applied to every document PDF issued from then on (existing documents keep the look they were issued with, because the branding is frozen into each document's snapshot), and to the management-report PDFs (§7), which render live and so always reflect the current branding:

> **The logo is frozen by reference.** You send it as a data-URI, but an issued document's snapshot stores `branding.logoRef` (`{fileId, sha256, mime}`) rather than the image itself, so a snapshot stays a few kilobytes instead of a few hundred. The bytes are pinned by that hash and the rendered PDF is unaffected. If you read a snapshot back (`GET /documents/:id`) and want the image, fetch the file by its id; documents issued before this change still carry an inline `branding.logo`.

```bash
curl -X PATCH "$BASE/businesses/$BID" -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d '{
  "branding": {
    "logo": "data:image/png;base64,iVBOR...",
    "tagline": "איפור כלות וערב",
    "accentColor": "#7A1FA2",
    "footerText": "תודה שבחרתם בנו! לקביעת תור: 052-1111111",
    "template": "stripe"
  }
}'
```

| Field | Rules |
|---|---|
| `logo` | `data:image/png|jpeg|webp;base64,...` URI, decoded ≤ 400KB. Rendered ~92px square at the document header |
| `tagline` | ≤ 120 chars, shown under the business name in the accent color |
| `accentColor` | `#rrggbb`, colors the tagline, divider, מקור/העתק badge and table headers (default green `#1F6B4A`) |
| `footerText` | ≤ 240 chars, centered line above the footer (thank-you note, booking phone, etc.) |
| `website` | ≤ 200 chars, printed as a link in the business block |
| `template` | The page design: `classic` (the default: the business header, the accent-colored table head, the digital-signature stamp) or `stripe` (the minimal layout of a Stripe receipt, mirrored to Hebrew: a plain title, a label/value grid, one headline amount, hairline tables, no fills; the accent color is spent on links only). Omit or `null` for `classic` |

Both designs carry everything the tax rules require (מקור/העתק marking, the VAT ladder, the allocation number, the "מסמך ממוחשב" signature footer), so pick by taste. Both are light: a signed one-page document is roughly 75KB in the classic design and 50KB in the minimal one, and a two-page minimal document about 85KB.

Patch semantics per field: send a key to set it, `null` to remove it, omit to keep it. `"branding": null` clears everything. A per-issue `{"branding": {...}}` on the issue call overrides the stored defaults for that document only.