### Zoho Partner Store — a read-only API that returns bare arrays

Three things differ from every other service in zone: the API is **entirely read-only**, responses are a **bare JSON array** with no envelope, and `per_page` is capped at **300**.

#### There is nothing here to break

All 15 commands are `GET`. There is no create, update or delete — the Partner Store API reports what Zoho has already billed and paid. So this is the one service where an agent can explore freely; the risk is misreading the numbers, not damaging anything.

#### The response is an array, not an envelope

Every other Zoho service wraps rows in an object — CRM's `{"data":[…]}`, Books' `{"code":0,…,"page_context":{}}`, Desk's `{"data":[]}`. Partner Store returns the array itself:

```bash
zone partner transactions list --per-page 50 --json
# [ { "transaction_id": …, "entity": "Zoho UAE", … }, … ]
```

Code that reaches for `.data` or `.page_context` finds `undefined` here. There is also **no total count and no "has more" flag**, so paging means requesting a page and stopping when it comes back shorter than `--per-page`.

#### `per_page` maxes at 300

```bash
zone partner transactions list --per-page 300 --page 1 --toon
zone partner transactions list --per-page 300 --page 2 --toon
```

Asking for more is a hard error, not a silent clamp:

```
HTTP 400: Invalid per_page value found, per_page maximum can be 300
```

Verified live. Use 300 and walk `--page` until a short page arrives.

#### Three views of the same money

| Command group | What it answers |
|---|---|
| `zone partner subscriptions list` | what the customer is on — plan, pricing type, billing frequency, renewal dates |
| `zone partner transactions list` | what Zoho actually billed — the money events |
| `zone partner commissions list` | what Zoho owes or paid **you** on those transactions |

They do not line up one-to-one. A subscription produces many transactions over time, and a transaction may produce a commission later, in a different payout, from a different Zoho entity — so reconciling means joining on ids and dates, not assuming row counts match.

```bash
zone partner subscriptions active --per-page 300
zone partner subscriptions get <subscriptionId>
zone partner subscriptions transactions <subscriptionId> --transaction-date-from 2026-01-01
zone partner transactions invoiced --transaction-date-from 2026-01-01 --transaction-date-to 2026-06-30
zone partner commissions list --entity "Zoho UAE" --per-page 300
```

#### Commissions come from several Zoho entities

A commission row carries an `entity` — the Zoho legal entity that billed the customer. A single partner account routinely sees **Zoho Singapore, Zoho UAE, Zoho Saudi Arabia, Zoho Egypt, Zoho US and Zoho Netherlands** in the same list, each with its own payout and currency.

That matters when totalling: summing a commission amount across entities without checking currency produces a number that means nothing. Group by `entity` (and by `payout_id`) before you add anything up.

`--entity`, `--email`, `--service-name`, `--date` and `--transaction-date` filter the list server-side; prefer them over pulling everything and filtering locally, because of the 300-row ceiling.

#### Filtering by date

Transactions and subscriptions take explicit ranges rather than a single date:

- `--transaction-date-from` / `--transaction-date-to`
- `--start-from` / `--start-to`, `--next-from` / `--next-to` (subscription start and next-billing)
- `--registration-date-from` / `--registration-date-to` on leads

`commissions list` is the odd one: it takes a single `--date` and a single `--transaction-date`, not a range.

#### Invoices are a binary download

```bash
zone partner transactions invoice-attachment <transactionId> --out ./invoice.pdf
```

This returns a file, not JSON — give it `--out` or you get binary on stdout.

#### Snapshotting

```bash
zone partner pull -o ./partner-data
```

Writes leads, subscriptions, transactions and commissions to disk. Because the API is read-only and capped at 300 rows a page, a pull is the sensible way to get a full picture once and then work locally.

#### Errors → what to do

| What you see | Meaning | Do |
|---|---|---|
| `per_page maximum can be 300` | asked for more than the cap | use `--per-page 300` and page |
| `.data` or `.page_context` is undefined | the response is a bare array | index the array directly |
| a page looks complete but rows are missing | there is no total or has-more flag | keep paging until a page is shorter than `--per-page` |
| commission totals look wrong | rows span Zoho entities and currencies | group by `entity` and `payout_id` first |
| exit 3 | not signed in — Partner Store is its own consent | human runs `zone login partner` |
| exit 4 | the token lacks the Partner Store scopes | human re-logs in that service |

> Command names, paths and flags come from the installed specs. The bare-array response shape, the 300-row `per_page` cap and its exact error text, and the multi-entity commission rows were **verified live against a real Zoho Partner Store account** while writing this. No write exists in this API, so nothing was modified.
