Fetch reports and files through the API
Reports and files are not pushed to an SFTP server. You fetch them with the API, with a token that has the right for each call. This page shows which call gets which file, how to scope a call to one client, and how to generate the client reports on demand. For what each report contains and who receives it, see Reports and files Quiddly sends and Client Portal, Reports.
| You want | Call | Right |
|---|---|---|
| Reports Quiddly sent to a client (settlement notes, activity, payment and booked invoice reports, scheduled reports) | POST /reports/distribution-archive/search, then GET /reports/distribution-archive/<id>/file |
ReadReportArchive |
| Generated client reports by type and status | POST /reports/transaction-reports/search, then GET /storage/<fileName> |
SearchTransactionReports |
| Payout files | POST /payout-batches/search, then GET /storage/<fileName> |
SearchPayoutBatches, ReadPayoutFile |
| Payout journal as PDF | POST /reports/query-reports/QR.200021/query?format=pdf |
QueryReport |
| Query reports (financed invoices, payments, ledgers, …) | POST /reports/query-reports/<id>/query |
QueryReport, ReadQueryReport |
| BGMAX and KTL files | PUT /bookkeeping-files/generate, POST /bookkeeping-files/search, GET /storage/<fileName> |
GenerateBookkeepingFile, SearchBookkeepingFiles |
Which token, and how to scope it to a client
Section titled “Which token, and how to scope it to a client”Use a service account at admin level (a SYSTEM role account, see
Authentication). One token reaches every client,
and you scope a call to a client yourself:
- Archive and search calls take a
clientIdin the body. The exception isPOST /payout-batches/search: a payout batch does not belong to one client, and aclientIdin that body is refused with a 400. - Query reports take a
clientIdfilter in the payload, for the reports that define one.
The alternative is a client-specific token, which a client creates in the
Client Portal under Configure, Integrations, Create new integration.
The token is shown once, when the integration is created. With a client token
the client is taken from the token: a clientId you send in a query report
filter is replaced by the token’s own client.
Use the admin-level account when you serve several clients, and a client token when an integration should only ever see one client.
Reports Quiddly sent to a client
Section titled “Reports Quiddly sent to a client”The distribution archive holds what the system has distributed to a client, and the files uploaded into it. It is the same list the client sees under Distribution Archive in the Client Portal.
curl -X POST "https://$HOST/reports/distribution-archive/search?limit=50&order=desc" \ -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \ -d '{ "clientId": "C.100100", "reportType": ["FACTORING_SETTLEMENT_NOTE", "ACTIVITY_REPORT_DAILY"], "fromDate": "2026-09-01", "toDate": "2026-09-30" }'Every filter is optional. reportType and currency are lists, and the dates
are YYYY-MM-DD. Rows come newest first (orderBy can only be
generatedDate), with the total in the X-Total-Count header.
reportType |
Report |
|---|---|
FACTORING_SETTLEMENT_NOTE, INVOICE_SETTLEMENT_NOTE, BUSINESS_LOAN_SETTLEMENT_NOTE, OVERDRAWN_SETTLEMENT_NOTE |
The settlement notes |
ACTIVITY_REPORT, ACTIVITY_REPORT_DAILY |
The monthly and daily activity reports, in any format |
PAYMENT_REPORT, BOOKED_INVOICE_REPORT |
The payment transaction report and the booked invoice report |
QUERY_REPORT |
A scheduled query report |
UPLOADED_REPORT, OTHER |
Files uploaded into the archive, and anything else |
Download one row with its id. Send the client again with an admin-level token:
curl "https://$HOST/reports/distribution-archive/$ID/file?clientId=C.100100" \ -H "Authorization: Bearer $JWT" -o reportThe file comes in the format it was made in, which the row shows in format.
Generated client reports by type and status
Section titled “Generated client reports by type and status”To find reports by type, client and status, search the transaction reports. A
report is GENERATED, then AUTHORIZED, then EXPORTED.
curl -X POST "https://$HOST/reports/transaction-reports/search" \ -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \ -d '{ "clientId": "C.100100", "type": "ACTIVITY_REPORT_DAILY_XML", "status": "EXPORTED" }'Each report carries its documents, with the type and fileName of each
file. Download a file by its name from the storage API:
curl "https://$HOST/storage/$FILE_NAME" -H "Authorization: Bearer $JWT" -o report.xmlReading a single report by id needs ReadTransactionReport. The type is one of:
type |
Report |
|---|---|
FACTORING_SETTLEMENT_NOTE, INVOICE_SETTLEMENT_NOTE, BUSINESS_LOAN_SETTLEMENT_NOTE, OVERDRAWN_SETTLEMENT_NOTE |
The settlement notes. Their Excel and XML files are listed among the documents of the same report |
FACTORING_SETTLEMENT_NOTE_XML, INVOICE_SETTLEMENT_NOTE_XML |
XML settlement notes that are reports of their own |
PAYMENT_TRANSACTION_CLIENT_REPORT, PAYMENT_TRANSACTION_CLIENT_REPORT_BGMAX |
The payment transaction report, as PDF and as BGMAX |
BOOKED_INVOICE_REPORT |
The booked invoice report |
ACTIVITY_REPORT, ACTIVITY_REPORT_XLSX, ACTIVITY_REPORT_XML |
The monthly activity report, one report per format |
ACTIVITY_REPORT_DAILY, ACTIVITY_REPORT_DAILY_XLSX, ACTIVITY_REPORT_DAILY_XML |
The daily activity report, one report per format |
Payout files and the payout journal
Section titled “Payout files and the payout journal”List the payout batches, then download the file of each batch. Exported batches
have status EXPORTED.
curl -X POST "https://$HOST/payout-batches/search" \ -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \ -d '{ "status": "EXPORTED" }'Each batch has a documents list with fileName for each payout file. Download
it from GET /storage/<fileName>, which needs ReadPayoutFile for a payout file.
The payout journal for one batch is a query report with the id QR.200021, which
requires a payoutBatchId filter. This is how you get it as a PDF:
curl -X POST "https://$HOST/reports/query-reports/QR.200021/query?format=pdf" \ -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \ -d '{ "select": [ { "field": "payoutDate" }, { "field": "receiver" }, { "field": "toChannel" }, { "field": "currency" }, { "field": "amount" } ], "filter": [{ "field": "payoutBatchId", "operator": "EQ", "value": "POB.1001" }], "limit": 1000 }' -o payout-journal.pdfAlways send a limit. Without one, the report’s own default applies, and the payout journal
defaults to 10 rows, so the PDF would hold only the 10 largest payouts of the batch. Use a limit
at least as large as the number of payouts in the batch.
Query reports
Section titled “Query reports”A query report is a saved report definition that you run with your own columns, filters and order. Read the definition first, to see which fields it allows:
curl "https://$HOST/reports/query-reports/$REPORT_ID" -H "Authorization: Bearer $JWT"This needs ReadQueryReport, and GET /reports/query-reports lists the reports
you can run. The standard reports have the same ids in every environment, and a
report built for one environment has its own, so confirm an id against the list.
Then run the report, with QueryReport. This example runs the standard Payments
report, QR.200001:
curl -X POST "https://$HOST/reports/query-reports/QR.200001/query?format=json" \ -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \ -d '{ "select": [ { "field": "invoiceNumber" }, { "field": "transactionDate" }, { "field": "amountCapital" }, { "field": "invoiceCurrency" } ], "filter": [ { "field": "clientId", "operator": "EQ", "value": "C.100100" }, { "field": "eventType", "operator": "EQ", "value": "PAYMENT" } ], "order": [{ "field": "transactionDate", "order": "DESC" }], "limit": 100, "page": 1 }'formatisjson(default),csv,pdforxlsx.selectis required and every field must be one the definition lists.- A filter takes
EQ,NE,GT,LT,GE,LEorIN, but only the operators the definition allows for that field. A definition can also require a filter. - For
IN, send the values as one string separated by commas. Spaces are ignored. - Page with
limitandpage.pageis the page number, starting at 1: the second batch of 100 rows is"limit": 100, "page": 2. Without alimit, the report’s own default limit applies, if it has one. For a large result, fetch it batch by batch rather than in one call.
BGMAX and KTL files
Section titled “BGMAX and KTL files”BGMAX files (Swedish clients) and KTL files (Finnish clients) are bookkeeping files. They are generated first, then listed, downloaded and marked exported. There is no shorter route, so build the four steps into your integration and monitor the result.
-
Generate with
PUT /bookkeeping-files/generate(GenerateBookkeepingFile). For BGMAX and KTL at least onefilterCodeis required.Terminal window curl -X PUT "https://$HOST/bookkeeping-files/generate" \-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \-d '{"clientId": "C.100100", "type": "BGMAX", "content": ["PAYMENTS"],"filterCode": ["ALL"], "fromDate": "2026-09-01", "toDate": "2026-09-30"}'One file is created per booking day and currency in the period. Generation runs in the background, so list the files after a few seconds.
-
List the files with
POST /bookkeeping-files/search(SearchBookkeepingFiles), filtering onclientId,typeandstatus(CREATEDorEXPORTED). -
Download each file from
GET /storage/<documentFileName>. -
Mark it exported with
PUT /bookkeeping-files/<id>/export(ExportBookkeepingFile). This only works while the file isCREATED.
See Export internal bookkeeping for the record fields and for SIE files.
Generate the client reports on demand
Section titled “Generate the client reports on demand”The daily routine generates, authorizes and exports the client reports. You can run the same three steps through the API. The calls work on all clients at once, and each needs its own right.
-
Generate with
PUT /reports/transaction-reports/generate(GenerateTransactionReports):Terminal window curl -X PUT "https://$HOST/reports/transaction-reports/generate" \-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \-d '{ "transactionDate": "2026-10-01", "override": false }'instanceProviderIdlimits the run to one instance provider, andoverridemakes the activity reports for the date again if they already exist. The call is refused with400 There can only be one collection of transaction reports in progress at a timewhile earlier transaction reports are still waiting to be authorized or exported (statusGENERATEDorAUTHORIZED). Payout batches do not block it, but generate the reports after the day’s payouts have been exported, so the settlement notes include them. -
Authorize with
PUT /reports/transaction-reports/authorize(AuthorizeTransactionReports), with the sametransactionDate. -
Export with
PUT /reports/transaction-reports/export(ExportTransactionReports), with the sametransactionDate. Exporting is what sends the reports to the clients.
The daily activity report has its own scheduled job each morning, so the run above may skip it. If you need it at another time, contact Quiddly support.