Reports export
Download a CSV export of sales or redemptions for a date range.
A single endpoint that generates a CSV export of either sales (orders) or
redemptions for a chosen date range, used by the dashboard's Reports page.
Requires an authenticated merchant session with the portal.reports
permission (admins bypass this check).
Successful responses are raw CSV, not JSON
Unlike every other BFF endpoint, a successful response here is not
{ "ok": true, "data": { ... } }. It is the CSV file body directly, with
Content-Type: text/csv and a Content-Disposition: attachment header.
Only error responses use JSON ({ "ok": false, "error": "..." }, a bare
string, not the nested { "message": ... } shape used elsewhere).
Gated by settlement mode, same as Analytics and Settlements
dataset=sales requires the merchant's settlement mode to make sales
insights available, and dataset=redemptions requires redemption insights
to be available. See Analytics for how
settlementMode determines this.
Export a report
GET /api/bff/reports/exportQuery parameters
| Param | Type | Required | Notes |
|---|---|---|---|
dataset | string | yes | sales or redemptions. |
range | string | yes | last_1d, last_7d, last_30d, or custom. |
startDate | string (YYYY-MM-DD) | required if range=custom | Inclusive start of the custom range, UTC midnight. |
endDate | string (YYYY-MM-DD) | required if range=custom | Inclusive end of the custom range, UTC end of day. |
A custom range cannot exceed 92 days, and startDate cannot be after
endDate. Each export is capped at 5000 rows (oldest beyond the cap are
silently excluded; rows are ordered newest first, so the cap drops the
oldest rows in range).
Response: sales CSV
Filename: sales-report-<start>-to-<end>.csv
| Column | Source |
|---|---|
date_sold | Order's createdAt, ISO timestamp. |
order_id | Order ID. |
buyer_or_recipient | buyerName, or the local part of buyerEmail if no name is set. |
gift_card_value | totalAmountMinor formatted as a decimal amount. |
payment_buyer | paymentStatus enum value. |
order_status | status enum value. |
payment_ref | paymentTransactionId, falling back to gr4vyTransactionId, or empty. |
Response: redemptions CSV
Filename: redemptions-report-<start>-to-<end>.csv
| Column | Source |
|---|---|
redeemed_at | Redemption's createdAt, ISO timestamp. |
gift_card_ref | The linked gift card's card-network code or QR code, falling back to the redemption's own qrCode. |
store_location | retailStoreName, falling back to source, or "POS App". |
device_pos | source, or "POS". |
redemption_status | SUCCEEDED or FAILED. |
redeemed | redeemAmountMinor formatted as a decimal amount. |
remaining | Remaining balance after this redemption, parsed from the redemption's stored upstream response payload (tries valueRemains, remainingBalance, then balance, at the top level or nested under data/giftCard). Empty if not derivable. |
All CSV fields are quoted if they contain a comma, quote, or newline, with embedded quotes doubled per standard CSV escaping.
Errors
All error responses are JSON with { "ok": false, "error": "<message>" }.
| Status | Cause |
|---|---|
| 401 | No session. |
| 404 | Session user has no associated merchant. |
| 403 | Non-admin user's role lacks the portal.reports permission, or the requested dataset's insight type is unavailable for this merchant's settlement mode. |
| 400 | Missing or invalid dataset/range, or an invalid/out-of-bounds custom date range. |
| 500 | Unexpected internal error while generating the report. |