SettleMint
API referenceGuides

Generate and download investor statements

Configure investor statement policy, generate a statement for a final date range, and download statements for the caller's own wallets.

Overview

The platform produces scheduled statements per wallet and chain, at the cadence set by the organization's policy. You can also request a statement for a specific date range. The policy selects which sections appear: opening and closing positions, movements, fees, and realized and period-end unrealized profit and loss per security.

When selected, profit and loss uses weighted-average cost. The platform skips that calculation when the policy omits the section. Trading fees are excluded from profit and loss and appear only when the Fees section is selected. A figure is marked incomplete when the cost basis or an indexed price is missing, such as a held position with no cost-basis history.

The platform produces only the formats selected in the policy. When both CSV and PDF are selected, the editions contain the same figures. The CSV keeps full addresses and transaction hashes, which the PDF shortens to fit the page. The same figures are also available as CSV from GET /api/v2/user-pnl/export.

The PDF is rendered inside the platform with no external calls, using the organization's logo, colors and fonts from Organisation theme. The same statement and theme produce the same file digest.

List and download access is limited to the caller's own wallets in the request's organization and chain. A statement for another wallet answers 404 rather than revealing that it exists. This restriction also applies to organization owners and admins, and platform administrators, even though they can generate statements for other holders.

Read or replace the statement policy

An organization owner or admin, or a platform administrator, can read the organization's policy with GET and replace it with PUT. Other members receive 404.

curl "https://your-instance.example.com/api/v2/reporting/statements/policy" \
  -H "X-Api-Key: <your api key>"

The cadence is daily, weekly, monthly, or quarterly. The sections are a non-empty selection of positions, movements, pnl, and fees. The formats are a non-empty selection of csv and pdf. Without a saved policy, the platform uses monthly statements with all sections in both formats.

PUT replaces the complete policy. For example, this request selects weekly statements with positions and movements in CSV only.

curl -X PUT "https://your-instance.example.com/api/v2/reporting/statements/policy" \
  -H "X-Api-Key: <your api key>" \
  -H "Content-Type: application/json" \
  -d '{
    "cadence": "weekly",
    "sections": ["positions", "movements"],
    "formats": ["csv"]
  }'

Both policy routes return the policy in data.

When a scheduled statement appears

The platform checks once an hour by default for the last three closed periods in UTC at the organization's chosen cadence. It writes statements only after the chain is final past the period's end. A scheduled statement covers a wallet that held an opening or closing balance, moved units, or paid fees during the period. Other wallets are skipped.

Balances come from the historical-balances feature. A security issued without that feature has no balance history, so its statement lines show movements against a zero balance and the statement reports reconciled: false.

Generate a statement for a date range

A caller can generate a statement for one of their own wallets. An organization owner or admin, or a platform administrator, can also generate one for another holder within the request's organization and chain. Other members receive 404 if holder is not one of their wallets.

curl -X POST "https://your-instance.example.com/api/v2/reporting/statements" \
  -H "X-Api-Key: <your api key>" \
  -H "Content-Type: application/json" \
  -d '{
    "holder": "0x1234567890abcdef1234567890abcdef12345678",
    "start": "2026-09-10T00:00:00.000Z",
    "end": "2026-09-20T00:00:00.000Z"
  }'

start is inclusive and end is exclusive. The start must precede the end, and the range can cover at most 366 days; otherwise the request returns 400. The example covers September 10 through September 19 in UTC. The stored period and response use an inclusive periodEnd of 2026-09-19T23:59:59.999Z.

A successful request returns 200 with the statement summary in data. Generation uses the policy's sections and formats and produces a statement even when the wallet has no activity. Repeating the same holder and range within the same organization and chain returns the existing statement. It does not regenerate it under a changed policy.

ErrorHTTP statusMeaning
DALP-0754422StatementRangeRefused with reason range-not-final: the requested period end is not final on the chain. Wait for finality before retrying.

The error's periodEnd uses the same inclusive end as the stored statement. The refused request writes no statement.

List the caller's statements

curl "https://your-instance.example.com/api/v2/reporting/statements" \
  -H "X-Api-Key: <your api key>"

The list includes scheduled and on-demand statements. Each entry includes the statement id, the account it covers, periodStart and inclusive periodEnd, the openingBlock and closingBlock the balances were read at, the available formats, and reconciled. reconciled is true when, for every security, the opening balance plus the movements listed equals the closing balance. Treat a statement with reconciled: false as incomplete and raise it with the operator.

Download one edition

curl "https://your-instance.example.com/api/v2/reporting/statements/<statementId>/download?format=pdf" \
  -H "X-Api-Key: <your api key>"

format is csv or pdf and must be one of the statement's available formats. Requesting an edition that was not generated returns 404. The response holds a downloadUrl that stays valid for 15 minutes, the file's mimeType and contentLength, and digest, the SHA-256 of the file. Fetch the file from downloadUrl and compare its SHA-256 with digest before you store or forward it. Request a new link when one expires; the file behind it never changes.

On this page