GET /statements

Get all statements

Retrieve a list of all available royalty statements for the authenticated user, ordered by period descending. Each statement includes a periods_covered array that indicates which actual sales periods are included in the payment, which may differ from the payment period when payments have been skipped or unclaimed in certain months. It is normal for multiple statements to cover overlapping periods if payments were delayed or reissued.

Note: The labelgrid_fee field shows the fee rate that was in effect when this statement was generated. Actual fees applied to individual line items may differ from this reference value. Refer to the detailed CSV export or transactions ledger for precise fee calculations per line item.

Opt-in per-label filtering: pass any of filter[label_id], filter[release_id], filter[isrc] or filter[upc] to switch to server-recomputed per-label gross-revenue totals sourced from the royalty line-item layer (grouped by payment period). The filtered rows carry a scope of label, a single monetary gross_usd, and a meta.gross_definition discriminator; all account-level-only fields (amount, opening_balance, tax/vat/transfer, total_due_usd, invoice_number, date_paid) are null. gross_usd matches the customer-facing UI + CSV column of the same name: gross revenue AFTER the statement-provider fee (e.g. Merlin/Orchard) and BEFORE LabelGrid platform/UGC fees; net revenue (after LabelGrid fees) and the final payout are on this statements endpoint (unfiltered). filter[start_date]/filter[end_date] (Y-m-d) narrow by payment period and require an entity filter. Only labels you directly own are visible; an unowned label_id returns 404 and an unowned upc/isrc returns an empty data array. With no filter the response is unchanged.

This endpoint returns one of two shapes depending on whether an entity filter is present. The @response schema below is the union of both — filtered-only keys (scope, filter, gross_usd) and the top-level meta block are present only in filtered mode, and every account-level field is nullable so a filtered row (where those fields are null) validates against the same schema.

Per-release rollup: add group_by=release (which requires filter[label_id]) to get one row per release under that label, grouped by payment period, instead of one per-label total. Amounts not attributable to a specific release (and any per-release rounding residue) surface as an explicit remainder row with release_id: null per period — never silently apportioned or dropped — so the per-release rows plus the remainder always sum exactly to the per-label total the non-grouped path returns for the same filters. Grouped rows carry scope: "release" and a release_id (null on the remainder row); meta adds group_by: "release". Any other group_by value, or group_by=release without filter[label_id], returns 422.

Parameters

Responses