Transactions & Receipts
Read the immutable record of every identified interaction: list and inspect transactions today, with receipts, voids, disputes, settlements, and reconciliation shape-frozen and on the way.
Overview
A transaction is the closed record of what happened in a session: who was identified, what they bought, which offers applied, how they paid, and what each money class moved. You can list and inspect transactions today; the void, receipt, dispute, settlement, and reconciliation operations are shape-frozen but not yet mounted.
Read The Decisioning Model first if you have not. A transaction is what the close call writes, and it carries the same two-class money split as every other surface.
These are read and operations endpoints, not the session spine. You create a transaction by closing a session (Checkout Sessions) or by debiting a wallet (Payments & Redemption). This page is about everything that happens to that record afterward.
Receipt-of-record: every identified transaction gets one
Every identified transaction produces a brand-wallet receipt, regardless of how it was paid. A wallet-paid order, a cash-paid order, and a card-paid order all generate the same receipt-of-record the moment the customer is resolved on the session. The tender does not gate the receipt; identity does.
This is the difference between a payments shim and a decisioning record. Feddi captures the transaction because the customer was identified, not because Feddi moved the money. A cash sale to a known customer is a first-class transaction with line items, applied offers, and attribution, even though no balance changed.
Use include_unidentified=false (the default) to see only identified transactions, the ones that carry a customer and a receipt-of-record. Set it to true only when you need the anonymous-session rows merged in.
Operations
This domain mixes maturities. Two read operations are Beta and callable today; everything that mutates or reports is Planned.
| Operation | Method + path | Maturity |
|---|---|---|
| List transactions | GET /{integrationId}/transactions | Beta |
| Get one transaction | GET /{integrationId}/transactions/{transactionId} | Beta |
| Void a transaction | POST /{integrationId}/transactions/{transactionId}/void | Planned |
| Render a receipt | GET /{integrationId}/transactions/{transactionId}/receipt | Planned |
| Reprint a receipt | POST /{integrationId}/transactions/{transactionId}/receipt/reprint | Planned |
| Resend a receipt | POST /{integrationId}/transactions/{transactionId}/receipt/resend | Planned |
| Unattach a customer | POST /transactions/{id}/unattach | Planned (compensation) |
| Open a dispute | POST /transactions/{id}/disputes | Planned |
| Read a dispute | GET /transactions/{id}/disputes/{disputeId} | Planned |
| Resolve a dispute | PATCH /transactions/{id}/disputes/{disputeId} | Planned |
| Daily settlement | GET /{integrationId}/settlements/daily | Planned |
| Monthly settlement | GET /{integrationId}/settlements/monthly | Planned |
| 3-way reconciliation | GET /{integrationId}/reconciliation/statement | Planned |
| Bulk export | GET /{integrationId}/transactions/export | Planned |
| Terminal close (Z-report) | POST /terminals/{id}/close | Planned |
The Planned operations are shape-frozen in the contract but not yet mounted. Wire them, but treat them as not-callable until they flip. The 95 Planned endpoints across the API are provisional: designed and reserved, not implementation-verified. The authoritative live list is always GET /v1/partner/capabilities and GET /v1/partner/openapi, never this page alone. See Availability & Maturity.
List transactions (Beta)
GET /{integrationId}/transactions returns a cursor-paged feed of transaction summaries, scoped to your integration. Pass an x-api-key. Reads do not carry the request envelope.
Filter by status: pending, completed, failed, partially_refunded, refunded.
Merge in transactions from anonymous sessions (no resolved customer). Default false.
Filter to a single branch (UUID).
Inclusive lower bound on created_at (RFC3339).
Inclusive upper bound on created_at (RFC3339).
Opaque cursor from the prior page's meta.next_cursor.
Page size. Default 50, max 200.
curl "https://api.feddi.io/v1/partner/{integrationId}/transactions?status=completed&limit=50" \
-H "x-api-key: $FEDDI_API_KEY"
{
"ok": true,
"data": [
{
"transaction_id": "tx_77c1",
"receipt_number": "RCT-2026-000812",
"transaction_type": "PAYMENT",
"transaction_subtype": "BALANCE",
"status": "completed",
"amount_minor": 4500,
"currency": "QAR",
"applied_discount_minor": 500,
"customer_phone": "+97433001122",
"customer_name": "Layla A.",
"identified_method": "qr",
"branch_id": "22222222-2222-2222-2222-222222222222",
"branch_name": "City Center",
"partner_session_id": "ord-99812",
"feddi_session_id": "33333333-3333-3333-3333-333333333333",
"created_at": "2026-06-05T09:14:00Z"
}
],
"error": null,
"meta": {
"request_id": "req_tl1",
"idempotency_replayed": false,
"api_version": "2026-06-01",
"next_cursor": "eyJjIjoxMDB9",
"has_more": true,
"data_completeness_score": 71
}
}
Pass this back as the cursor query param to fetch the next page. Absent on the last page.
true when another page exists. Stop paging when it is false.
Get one transaction (Beta)
GET /{integrationId}/transactions/{transactionId} returns the full detail for one record: the flattened customer, wallet, program, branch, brand, and enterprise; reconstructed line_items; the applied_offers that touched the charge; and related_transactions so you can render the full money lineage of an order (refunds, the original deposit, sibling rows that share a multi-transaction group).
Money is minor units plus an explicit currency. Metadata is sanitized server-side, so redemption secrets never leak into the response.
curl "https://api.feddi.io/v1/partner/{integrationId}/transactions/tx_77c1" \
-H "x-api-key: $FEDDI_API_KEY"
{
"ok": true,
"data": {
"transaction_id": "tx_77c1",
"receipt_number": "RCT-2026-000812",
"transaction_type": "PAYMENT",
"transaction_subtype": "BALANCE",
"status": "completed",
"amount_minor": 4500,
"currency": "QAR",
"applied_discount_minor": 500,
"customer": {
"wallet_user_id": "wu_5512",
"phone": "+97433001122",
"name": "Layla A.",
"identified_method": "qr",
"customer_state": "verified"
},
"wallet_id": "wal_5512",
"wallet_program_name": "VIP Rewards",
"branch": { "id": "22222222-2222-2222-2222-222222222222", "name": "City Center", "status": "ACTIVE" },
"partner_session_id": "ord-99812",
"feddi_session_id": "33333333-3333-3333-3333-333333333333",
"line_items": [
{ "sku": "LATTE-L", "name": "Large Latte", "quantity": 2, "unit_price_minor": 2000, "extended_price_minor": 4000, "discount_minor": 0, "tax_minor": 200, "category": "beverages" },
{ "sku": "CROISSANT", "name": "Butter Croissant", "quantity": 1, "unit_price_minor": 1000, "extended_price_minor": 1000, "discount_minor": 500, "tax_minor": 25, "category": "bakery" }
],
"applied_offers": [
{ "offer_id": "off_22", "name": "Croissant 50% off", "discount_minor": 500, "source": "rule" }
],
"related_transactions": [
{ "transaction_id": "tx_dep_44", "transaction_type": "DEPOSIT", "amount_minor": 10000, "status": "completed", "created_at": "2026-06-04T18:00:00Z" }
],
"created_at": "2026-06-05T09:14:00Z",
"updated_at": "2026-06-05T09:14:00Z"
},
"error": null,
"meta": { "request_id": "req_td1", "idempotency_replayed": false, "api_version": "2026-06-01", "data_completeness_score": 92 }
}
A transaction belonging to another integration resolves to FORBIDDEN (403), never NOT_FOUND. An id that is genuinely not visible to your integration is NOT_FOUND (404). Cross-tenant isolation is enforced per record. See Idempotency & Errors.
Corrections: void vs unattach vs dispute (Planned)
Three distinct compensations exist for three distinct mistakes. They are shape-frozen and not yet callable. Do not conflate them.
Void: same-day, full-amount, in-window correction
POST /{integrationId}/transactions/{transactionId}/void reverses a recent transaction inside a grace window (default 30 minutes). For a wallet payment it credits the debited actual balance back; for a credit to a PENDING_PROOF proto-wallet it claws back the LOCKED promo instead. A reason from a fixed enum is required. Voiding outside the window needs a manager_id override. Per-cashier void rate is capped (RATE_LIMITED, 429). It is idempotent on the Idempotency-Key header: a double-void replays the original reversal and never double-credits.
Unattach: wrong customer, surgical detach
POST /transactions/{id}/unattach disassociates a customer who was attached by mistake (the cashier picked the wrong person). It does not move money. It is the surgical un-attach of a disputed or misattributed receipt: the transaction stays, the customer link is removed, the action is audited, and repeated unattach by one cashier increments an anomaly flag. Idempotent on the Idempotency-Key header.
Dispute: investigation, not a reversal
POST /transactions/{id}/disputes opens a customer dispute. Opening a dispute is an investigation, not a money movement. Read its state with GET .../disputes/{disputeId} and resolve it (refund, partial, or reject) with PATCH .../disputes/{disputeId}. A resolution that refunds is the path for after-window, partial money-back; a void is the in-window, full-amount path.
Receipts: get, reprint, resend (Planned)
The receipt-of-record can be rendered and re-delivered without changing the transaction. These are shape-frozen.
GET /{integrationId}/transactions/{transactionId}/receiptrenders the receipt-of-record (html, pdf, or thermal).POST /{integrationId}/transactions/{transactionId}/receipt/reprintreprints a lost or jammed receipt, or a manager copy.POST /{integrationId}/transactions/{transactionId}/receipt/resendre-delivers a receipt to the customer's wallet or SMS.
Settlement and reconciliation (Planned)
These reporting surfaces close the books. They are ledger-and-report endpoints, never custody surfaces: Feddi never holds the money (see The Decisioning Model).
Daily settlement
GET /{integrationId}/settlements/daily. A deferred-revenue settlement statement for one day.
Monthly settlement
GET /{integrationId}/settlements/monthly. The financial-close statement plus CSV/XLSX export.
3-way reconciliation
GET /{integrationId}/reconciliation/statement. Reconciles the Feddi ledger against the POS till and the bank, and flags mismatches.
Terminal close (Z-report)
POST /terminals/{id}/close. The cashier submits the drawer count and shift window; Feddi returns the end-of-day Z-report. Idempotent on the Idempotency-Key header.
GET /{integrationId}/transactions/export bulk-exports transactions as CSV or XLSX (synchronous for small ranges, asynchronous for large ones).
Because settlement, reconciliation, and export are Planned, do not design a close-of-books workflow that assumes they respond today. Build the daily list-and-inspect path against the Beta GET /{integrationId}/transactions feed now, and check GET /capabilities before wiring the reporting calls.
Where to go next
Checkout Sessions
The session whose close writes the transaction you read here.
Payments & Redemption
The promo-first debit that produces a wallet-payment transaction.
Money: Actual vs Promotional
The two-class split that a void reverses and a detail row breaks out.
Idempotency & Errors
Idempotency-Key replay on voids, plus 403 vs 404 cross-tenant rules.