---
title: "Create or run companies transactions bulk approve"
method: POST
path: "/accountant/companies/{customerId}/transactions/bulk-approve"
tags: ["Accountant Portal"]
---

# Create or run companies transactions bulk approve

`POST /accountant/companies/{customerId}/transactions/bulk-approve`

## Request

- Base URL: `https://api.medianfi.com/api/v1`
- URL: `https://api.medianfi.com/api/v1/accountant/companies/{customerId}/transactions/bulk-approve`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Generated minimal contract (#1940): parameters, auth, and status codes are authoritative; see the route handler for the exact body/response shape. Enrichment tracked by the x-median-spec-stage marker.

## Request body

- object

## Response `200`

Success envelope. `data` is the bulk summary (`requested`, `processed`, `skipped`, `failed`, `results` with one item per distinct id) plus `stripeRevenueStillHeld` (#3039): the ids of Stripe counterparty-history suggestions that this request approved, or found already categorized on their suggested account, and whose Stripe revenue entry still has no account to post to after the request tried to write their merchant rule (the write failed, or the merchant or account cannot carry a rule). Those rows read categorized while their revenue stays held; send the same request again (a signed-in accountant's request writes the missing rule of an already categorized suggestion and reports the row as `skipped`), or use the single approve route. Empty when there is none. An already categorized suggestion whose revenue account resolves is left alone and its existing rule is not changed. Split rows are approved status-only, get no rule and are never listed here. Bulk-approve never changes an existing merchant rule (decided before any row is written): a suggestion still in review whose Stripe revenue account already resolves is approved with no rule write when that account is the suggested one, and comes back as a `failed` result, untouched, with reason `This Stripe revenue row's customer already has a rule or revenue account that differs from the suggested one; review it individually` when it is another account. The same `failed` result is returned, on the in-review path and on the already-categorized retry path, when the customer's exact merchant rule already exists and names another account of any type (for example an expense account, which gives no revenue authority); when that rule names the suggested account, no rule is written. A rule is never moved to another account by this route: it is created, or rewritten with the account it already names. A row whose account, merchant rule or revenue authority cannot be read is likewise not approved: `failed`, reason "This Stripe revenue row's merchant rule could not be checked; it was not approved. Try again". Selected suggestions that would write the same merchant rule with different suggested accounts all come back `failed`, untouched, with reason `Selected Stripe revenue rows from the same customer suggest different accounts; approve them individually`; with the same account they are approved and share one rule.

- object
  - `data` object
    - `stripeRevenueStillHeld` string[]: Transaction ids of approved Stripe counterparty-history suggestions whose revenue is still held because no merchant rule could be written (#3039). Empty when none.

## Other responses

- `401`: Authentication required
- `403`: Insufficient permissions or not assigned to the company. Also returned to a service API key, before any row is written, when the request would write a merchant rule: a selected row is a Stripe counterparty-history suggestion (categorizationSource stripe_counterparty_history, not split, with a suggested category) that is either still in review, or already categorized while its Stripe revenue entry has no account to post to. Approving such a row writes the customer's merchant rule, which is what lets its Stripe revenue entry post, and the service token never writes a rule. The whole request is refused and `detail` names the transaction ids (the first 20, then `and N more`); resend without them and leave those rows to an accountant. An already categorized suggestion whose revenue account resolves is not refused (it is skipped). A split suggestion is outside this check: the token approves it status-only, as any split row, no rule is written and its Stripe revenue stays held. If a selected row cannot be read, the service key's request fails as a whole with the read error and nothing is written. The service key is refused for every such suggestion still in review, including one whose revenue account already resolves (no rule would be written): confirming a history suggestion is refused for it on the single approve route as well. A signed-in accountant's bulk-approve approves a suggestion at its suggested category and writes that rule, as the single approve route does (#3039, J-417).
- `404`: Resource not found

---

[API](https://skmtc.dev/medianfi/apis/median-api.md) · [All operations](https://skmtc.dev/medianfi/apis/median-api/llms.txt) · [OpenAPI document](https://skmtc.dev/medianfi/apis/median-api/revisions/20090ea32b0d?raw)
