Reports run asynchronously: you start a generation, poll its status, then download the result. All three endpoints need the reports.view claim.
1

Generate

POST /reports with:
{ "reportType": "transactions", "fromDate": "2026-05-01", "toDate": "2026-05-31" }
Returns 202 with an executionId.reportType is one of: MT940, customers, fees, transactions, card_transactions, accounts, cards. For MT940, an optional "version": 2 selects the newer internal generator (ClearBank programs).
2

Poll

GET /reports/status/{executionId}state is RUNNING, SUCCEEDED, FAILED, or CANCELLED, with submittedAt / completedAt.
3

Download

Once SUCCEEDED: GET /reports/{executionId}{ "url": … }, a presigned S3 URL valid for 1 hour.
Results are scoped by the operator’s claims — operators with customer-scoped roles only see their own customers’ data.
If you integrated against the old docs: the paths changed. POST /reports/generate is now POST /reports, status is GET /reports/status/{executionId} (not /reports/{executionId}/status), and download is GET /reports/{executionId} (not …/download). There is no separate /reports/mt940 — MT940 is a reportType.