---
title: "Cancel Payment Batch"
method: POST
path: "/companies/{company_id}/payment-batches/{batch_id}/cancel"
tags: ["payments"]
---

# Cancel Payment Batch

`POST /companies/{company_id}/payment-batches/{batch_id}/cancel`

## Request

- Base URL: `https://app.zeno-works.ch` (the document declares no server; this is the origin it was published from)
- URL: `https://app.zeno-works.ch/companies/{company_id}/payment-batches/{batch_id}/cancel`
- Auth: none declared

``draft | pending_approval | approved → cancelled`` (accountant, ZCT-257).

``approved`` since ZENO-231: the release re-check can refuse an approved batch, and
nothing leaves Zeno before the first download, so cancel is its exit. ``exported`` is
final. Cancelling an approved batch withdraws its vouching for later batches'
first-time-supplier flags (warn-only; not recomputed).

Was member-level on the reasoning that nothing has moved money before approval — a
deliberate divergence from payroll's accountant-gated cancel. The owner withdrew that
on 2026-08-31, and the divergence goes with it: both cancels are accountant now.

⚠️ Note what the old rationale claimed and the code never did. It said "a member may
withdraw **their own** not-yet-approved batch"; there is no author scoping anywhere on
this path — `repo.get_batch` filters on `company_id` and `id` alone, and `created_by`
is written at creation and read by nothing. Before this gate, any member could cancel
any other member's `pending_approval` batch seconds before approval. The role gate
closes it for members; author scoping is still the right fix and is filed.

## Path parameters

- `company_id` string, required
- `batch_id` string, required

## Headers

- `authorization` string, nullable

## Cookies

- `access_token` string, nullable

## Response `200`

Successful Response

- ApPaymentBatchOut: A persisted AP pain.001 batch + its approval audit trail.
  - `id` string, required
  - `company_id` string, required
  - `debtor_bank_account_id` string, required
  - `status` 'draft' | 'pending_approval' | 'approved' | 'exported' | 'cancelled', required: AP payment batch approval lifecycle (doc/pipeline.md §"Exports (accounting hand-off)"). ``draft → pending_approval → approved → exported`` (+ cancel from draft/pending/approved — ZENO-231; ``exported`` is final). Rejection is a *transition* back to ``draft``, not a state — the ``rejected_*`` audit columns record the last rejection. The XML is downloadable only in ``approved``/``exported``; the first download stamps ``approved → exported``.
  - `execution_date` string, date, required
  - `msg_id` string, required
  - `nb_of_txs` integer, required
  - `ctrl_sum` string, required
  - `filename` string, required
  - `created_by` string, nullable
  - `created_at` string, date-time, required
  - `submitted_by` string, nullable
  - `submitted_at` string, date-time, nullable
  - `approved_by` string, nullable
  - `approved_at` string, date-time, nullable
  - `rejected_by` string, nullable
  - `rejected_at` string, date-time, nullable
  - `reject_reason` string, nullable
  - `exported_by` string, nullable
  - `exported_at` string, date-time, nullable
  - `cancelled_by` string, nullable
  - `cancelled_at` string, date-time, nullable
  - `items` ApPaymentBatchItemOut[]
    - `id` string, required
    - `item_id` string, nullable
    - `creditor_name` string, required
    - `iban` string, required
    - `amount` string, required
    - `currency` string, required
    - `instr_id` string, required
    - `end_to_end_id` string, required
    - `first_time_supplier` boolean

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/zeno-works/apis/zeno-api.md) · [All operations](https://skmtc.dev/zeno-works/apis/zeno-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zeno-works/apis/zeno-api/revisions/1eb93dde146c?raw)
