Skip to content
Linra Omni Developer Docs

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.

Terminal window
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.

Terminal window
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:

Terminal window
GET /api/v1/statements/by-number/STMT-PTR-EXAMPLE-0001-14

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:

Terminal window
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.

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: always false.

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.