Skip to main content
Reports are PDFs covering a closed date range, generated from the ledger. Two types exist:
  • accounting_transactions is a ledger-level listing of every entry in the period.
  • merchant_statement is a summarized statement for the period.
Generation is asynchronous and cached. The first request for a given type, range and currency queues a job and returns 202. Once the job finishes, the same request returns 200 with a download link. Repeating the request reuses the existing report rather than regenerating it. Paths are relative to https://api.southpay.io/api/v2.

Authentication and scope

Reports map to the balances resource, so GET requires balances:read, not a reports scope, which does not exist. Publishable keys are rejected.

Data availability

Reports only cover days that have fully closed. The latest available date is:
  • Yesterday, once the current UTC day has passed 12:00.
  • The day before yesterday, before 12:00 UTC.
Read the current boundary from available_through on the index endpoint rather than computing it yourself.

Request a report

GET /reports/accounting_transactions and GET /reports/merchant_statement. Scope balances:read. Both take the same parameters and return the same body shapes.
string
required
ISO date, inclusive. Missing or unparseable dates currently produce 500 rather than a validation error, so send a well-formed value.
string
required
ISO date, inclusive. Must be on or after start_date and no later than available_through.
string
Restrict to one settlement currency: USD, EUR, GBP, HKD, SGD, JPY, DKK, CHF, SEK or NOK. Anything else is ignored and the report covers all currencies.
The maximum range is 366 days.

Polling

Poll the same URL with the same parameters. The status code tells you where you are. Treat 202 as “not ready, try again”, not as success. A few seconds between polls is enough for typical ranges. A failed report is retried automatically on your next request. So is a pending report that has not been touched in five minutes, which recovers a job that died mid-run.
string
A presigned download link, valid for expires_in seconds.
integer
Always 3600. Fetch the PDF promptly, or re-request the report to mint a fresh link.
integer
The report record’s id. Also appears in the index listing.
url is a time-limited presigned download link. Treat it as opaque: follow it exactly as returned, query string included. The host is not a southpay.io domain, and neither the hostname nor the path shape is stable, so do not allowlist a hostname, parse the URL, or try to reconstruct it.

List recent reports

GET /reports. Scope balances:read. No parameters. Returns the 50 most recent reports for the store, newest first, plus the current availability boundary.
object[]
required
string
required
The latest date a report may end on, as of now. Use it to build a valid end_date.
Reports are cached per store, type, date range and currency. Requesting the same combination twice returns the same record. There is no way to force regeneration other than changing a parameter.

Errors

Pre-flight validation returns 422, but the error value is inconsistent: one is prose, the other two are machine codes carrying an extra field.
Missing or malformed date parameters return 500, not 422. Validate the format on your side before calling.
Last modified on August 21, 2026