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

# Create or run companies transactions approve

`POST /accountant/companies/{customerId}/transactions/{transactionId}/approve`

## Request

- Base URL: `https://api.medianfi.com/api/v1`
- URL: `https://api.medianfi.com/api/v1/accountant/companies/{customerId}/transactions/{transactionId}/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
  - `categoryGlAccountId` string, uuid
  - `notes` string
  - `reason` string: #3046: why the category was changed. One line of plain text (trimmed; no control, line-separator or text-direction characters, no HTML markup, and not the text '| Recategorization reason:'). Stored as the reasoning of the decision on the transaction timeline and appended to the replacement journal entry's description as ' | Recategorization reason: <reason>'. Absent leaves the decision as before and removes a reason left on the description by an earlier recategorize; a description that never carried one is unchanged. The reason is not sent to QuickBooks.
  - `learnMerchantRule` boolean: #3041: whether this approval writes or repoints the merchant rule for this transaction's merchant. true: a changed category does. Absent: a changed category, including the first category on an uncategorized transaction, applies to this transaction only and the rule is left alone; an approval that leaves the category unchanged writes a rule only when it confirms a Stripe counterparty-history suggestion. false: no rule is written in any case. Stripe revenue transactions (a Stripe charge, invoice or subscription payment, or a Stripe counterparty-history suggestion) are outside this choice: a category change on one always writes its exact company rule, because that rule is what lets the revenue entry post. The bookkeeping engine's feedback run is queued whatever the value; its output is a proposal for review.

## Response `200`

Success envelope; see the route handler for the payload shape

- object

## Other responses

- `401`: Authentication required
- `403`: Insufficient permissions or not assigned to the company. Also returned, before anything is written, when a service API key sends learnMerchantRule: true: the service token cannot create or retrain a merchant rule (#2383, #3039). Also returned to a service API key, before anything is written, when the request changes the category of a Stripe revenue row (a Stripe charge, invoice or subscription payment, or a row suggested from Stripe counterparty history): that change writes the customer's merchant rule whatever learnMerchantRule says, so an accountant must make the correction (#3039, J-413). Also returned to a service API key, before anything is written, when it approves a row suggested from Stripe counterparty history without changing its category, whether learnMerchantRule is absent or false: that approval writes the customer's merchant rule, and with false the row would be categorized while its Stripe revenue entry stays held, so an accountant must confirm it (#3039, J-417).
- `404`: Resource not found
- `422`: Business rule error; nothing is written. `error.title` is `TRANSACTION_CATEGORY_IS_BANK_ACCOUNT` when the approved category (explicit or the existing suggestion) is the GL account of the transaction's own bank or card account, `TRANSACTION_APPLIED_TRANSFER_MATCH_ACTIVE` or `TRANSACTION_BANK_OFFSET_UNIDENTIFIED` as on the accountant PATCH.

---

[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)
