Billing statements
List your billing statements, read one in full, and compute an ad-hoc provisional report.
Linra generates a persisted, immutable billing statement for you on a recurring cadence. Every statement is a snapshot of your wallet ledger over one fixed window — once generated, it never changes, even if a later event (a late-settled commission, a delayed return) affects a subsequent window.
1. List your statements
Section titled “1. List your statements”GET /api/v1/statements?page=1&pageSize=20{ "state": "SUCCESS", "payload": { "items": [ { "id": "22222222-2222-2222-2222-222222222222", "statementNumber": "STMT-PTR-EXAMPLE-0001-14", "sequenceNumber": 14, "period": { "from": "2026-01-01T00:00:00Z", "to": "2026-01-31T23:59:59Z" }, "generatedAt": "2026-02-01T03:00:00Z", "currency": "SAR", "totals": { "debits": 1200.50, "credits": 300.00, "net": -900.50 }, "locked": true } ], "pagination": { "page": 1, "pageSize": 20, "totalCount": 1, "totalPages": 1 } }}The list is intentionally lean — no embedded document, so a page of statements stays small. To read one statement’s full detail (every line), fetch it by ID.
There is no filter parameter on this endpoint beyond paging — every statement belongs to you, so there is nothing else to narrow by.
2. Get one statement’s full document
Section titled “2. Get one statement’s full document”GET /api/v1/statements/{id}{ "state": "SUCCESS", "payload": { "id": "22222222-2222-2222-2222-222222222222", "statementNumber": "STMT-PTR-EXAMPLE-0001-14", "sequenceNumber": 14, "period": { "from": "2026-01-01T00:00:00Z", "to": "2026-01-31T23:59:59Z" }, "generatedAt": "2026-02-01T03:00:00Z", "currency": "SAR", "totals": { "debits": 1200.50, "credits": 300.00, "net": -900.50 }, "locked": true, "document": { "sequenceNumber": 14, "statementNumber": "STMT-PTR-EXAMPLE-0001-14", "isProvisional": false, "period": { "from": "2026-01-01T00:00:00Z", "to": "2026-01-31T23:59:59Z" }, "generatedAt": "2026-02-01T03:00:00Z", "currency": "SAR", "totals": { "debits": 1200.50, "credits": 300.00, "net": -900.50 }, "lines": [ { "timestamp": "2026-01-15T10:22:00Z", "transactionType": "Debit", "referenceType": "Order", "amount": 132.25, "balanceAfter": 4867.75, "orderGoodsVatAmount": 17.25, "orderTotalAmountWithVat": 132.25 } ], "documentNature": "This is a commercial billing document for informational and reconciliation purposes. It is NOT a ZATCA-compliant legal tax invoice.", "isZatcaCompliantTaxInvoice": false } }}A statement belonging to another partner, or an unknown ID, returns a plain 404 NOT_FOUND_STATEMENT — never a 403, so you can’t tell the difference between “not yours” and
“doesn’t exist.”
You can also fetch a statement by its human-facing statementNumber instead of its id — same
response shape, same no-existence-leak 404:
GET /api/v1/statements/by-number/STMT-PTR-EXAMPLE-0001-14The document line shape
Section titled “The document line shape”Each document.lines[] entry is one wallet ledger row:
| Field | Meaning |
|---|---|
transactionType |
Debit | Credit | InternalTransfer (the last is reserved — no live path posts it today). |
referenceType |
Order | ManualAdjustment | Refund | Topup | SubscriptionPayment | SubscriptionRefund | SubscriptionCredit | Commission. A commission reversal (a return’s clawback) posts as a Commission-typed Debit — there is no separate CommissionReversal value; check transactionType to distinguish a commission credit from its reversal. |
orderGoodsVatAmount, orderCommissionVatAmount, orderTotalAmountWithVat, orderTotalCommissionWithVat, orderShippingFeeAmount, orderShippingFeeVatAmount, orderShippingFeeAmountWithVat, platformTaxRegistrationNumber, partnerTaxRegistrationNumber, orderPartnerIsVatRegistered, orderGoodsTaxClassification |
Best-effort order/VAT enrichment, populated only for Order-type rows. null means “enrichment unavailable this attempt,” never “zero” or “not applicable.” Don’t treat a null VAT field as zero VAT. |
3. Compute an on-demand provisional report
Section titled “3. Compute an on-demand provisional report”Need a figure for a window that hasn’t closed into a persisted statement yet? Compute one live:
GET /api/v1/statements/report?from=2026-02-01T00:00:00Z&to=2026-02-15T00:00:00Z{ "state": "SUCCESS", "payload": { "sequenceNumber": null, "statementNumber": null, "isProvisional": true, "period": { "from": "2026-02-01T00:00:00Z", "to": "2026-02-15T00:00:00Z" }, "generatedAt": "2026-02-10T09:00:00Z", "currency": "SAR", "totals": { "debits": 450.00, "credits": 0.00, "net": -450.00 }, "lines": [], "documentNature": "This is a commercial billing document for informational and reconciliation purposes. It is NOT a ZATCA-compliant legal tax invoice.", "isZatcaCompliantTaxInvoice": false }}from and to are both required — omitting either returns a 400 VALIDATION_MISSING_REPORT_RANGE.
This report is live-computed and never persisted. Re-running the exact same query later can
return a different figure if a late-settled event (a delayed commission reversal, a return that
posted after your first call) lands in the meantime. Treat it as a convenience for ad-hoc
reconciliation, never as a substitute for your persisted statements — its sequenceNumber and
statementNumber are always null, which is your signal that a given document is provisional.
Not a legal invoice
Section titled “Not a legal invoice”Every document — persisted statement or on-demand report — carries the same caveat, both as a human-readable string and a machine-checkable boolean:
documentNature: a free-text sentence stating this is a commercial billing document, not a legal tax invoice.isZatcaCompliantTaxInvoice: alwaysfalse.
Linra is the data source for ZATCA e-invoicing obligations (VAT figures, invoice-line data) — it does not issue the ZATCA-compliant legal invoice itself. If you need one, generate it from your own accounting system using this document’s figures as input.

