Domain GuidesTransactions & Receipts

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.

OperationMethod + pathMaturity
List transactionsGET /{integrationId}/transactionsBeta
Get one transactionGET /{integrationId}/transactions/{transactionId}Beta
Void a transactionPOST /{integrationId}/transactions/{transactionId}/voidPlanned
Render a receiptGET /{integrationId}/transactions/{transactionId}/receiptPlanned
Reprint a receiptPOST /{integrationId}/transactions/{transactionId}/receipt/reprintPlanned
Resend a receiptPOST /{integrationId}/transactions/{transactionId}/receipt/resendPlanned
Unattach a customerPOST /transactions/{id}/unattachPlanned (compensation)
Open a disputePOST /transactions/{id}/disputesPlanned
Read a disputeGET /transactions/{id}/disputes/{disputeId}Planned
Resolve a disputePATCH /transactions/{id}/disputes/{disputeId}Planned
Daily settlementGET /{integrationId}/settlements/dailyPlanned
Monthly settlementGET /{integrationId}/settlements/monthlyPlanned
3-way reconciliationGET /{integrationId}/reconciliation/statementPlanned
Bulk exportGET /{integrationId}/transactions/exportPlanned
Terminal close (Z-report)POST /terminals/{id}/closePlanned

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.

query
statusstring

Filter by status: pending, completed, failed, partially_refunded, refunded.

query
include_unidentifiedboolean

Merge in transactions from anonymous sessions (no resolved customer). Default false.

query
branch_idstring

Filter to a single branch (UUID).

query
created_fromstring

Inclusive lower bound on created_at (RFC3339).

query
created_tostring

Inclusive upper bound on created_at (RFC3339).

query
cursorstring

Opaque cursor from the prior page's meta.next_cursor.

query
limitinteger

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"
next_cursorstring

Pass this back as the cursor query param to fetch the next page. Absent on the last page.

has_moreboolean

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"

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}/receipt renders the receipt-of-record (html, pdf, or thermal).
  • POST /{integrationId}/transactions/{transactionId}/receipt/reprint reprints a lost or jammed receipt, or a manager copy.
  • POST /{integrationId}/transactions/{transactionId}/receipt/resend re-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).

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