Audience: POS integrators, resellers and partners who need transaction reports for their own merchants — daily, monthly or on demand.
Short version: Softpay is not a reporting system. Softpay gives you the transaction data; the reporting belongs in your own system. The most reliable way to get it is to store every transaction in your own database at the moment it happens, and treat any API call as a backfill or repair mechanism — not as your primary source.
1. Your three options
Option | Best for |
A. Capture in the POS during the payment flow | The recommended default. Full control, no polling, works for every merchant you serve. |
B. Batch/API pull from your backend | Backfilling, nightly reconciliation, repairing gaps. Also the right option if your POS is thin and your backend owns the data. |
C. Cloud API from a separate backend | When the system that needs the data is not the POS app at all (BI, ERP, accounting, a partner portal). |
Most partners use A as the primary mechanism and B as a nightly safety net. Option C applies when the reporting lives entirely outside the POS.
2. Option A — capture the data during the payment flow (recommended)
If your POS is already integrated with the AppSwitch SDK and follows Softpay's recommended transaction handling, you already have every transaction and its final state. Reporting then costs you almost nothing extra: you are just persisting what already passes through your code.
The pattern:
Generate and persist a
RequestIdbefore you start the payment. Store it in your backend, not only on the device. This is the key you will use for everything afterwards.Do not treat the request callback as the outcome.
onSuccess/onFailuretell you the request was delivered — not what happened to the payment.Use
onFinalas the definitive outcome. This is the moment a transaction reaches a final state.Write the transaction to your own reporting store at
onFinal. Key it onRequestIdso a repeated write is a no-op (idempotent).Use
GetTransactionfor recovery. If the app crashed, the process was killed, the network dropped, oronFinalnever arrived, look the transaction up byRequestIdand store the result. A lookup returningnullfor a transaction cancelled before the card tap is expected — not an error.
Do this and your reporting database is complete and correct by construction. Everything below is a safety net.
Rule of thumb: final state is the golden rule. The moment you know the final state, you may as well store it for reporting.
3. Option B — pull transactions in batches
For nightly reconciliation, gap-filling, or a POS whose backend owns the data, fetch transactions rather than capturing them.
AppSwitch batch fetch retrieves all transactions for a device in 24-hour batches. The batch number rolls over at 03:00 local time — this is not midnight, so align your report boundaries accordingly or you will chase phantom discrepancies.
Cloud API transactions endpoints let you filter by
appId,batchNumber, and a time window (for exampledays=1for the last 24 hours).
Run this as a scheduled job — e.g. every night, fetch yesterday's batch and reconcile it against what you already stored via Option A. Anything present in the batch but missing from your database is a gap worth investigating.
4. Option C — Cloud API from a separate backend
If the consuming system is not the POS app (BI warehouse, accounting, ERP, your own merchant portal), integrate the Cloud API server-to-server. Points that matter for reporting specifically:
OAuth client credentials are issued per integrator, and the same set is used across all your merchants. Handle token refresh automatically.
Your integrator account must be cloud-linked to every merchant whose data you want to read.
Never hard-code merchant references. Resolve them dynamically at runtime via the Cloud API
/merchantsendpoint or the Onboarding (MIA) API. Hard-coding works with one merchant and silently misattributes data as soon as a second one is onboarded — a mistake that is expensive to unwind after months of reports.Sandbox and Production are separate environments with separate base URLs and separate credentials. Build and test in Sandbox first.
Webhooks can push transaction events to you in near real time instead of polling. Events may arrive out of order or more than once, so deduplicate on the transaction identifier and respond HTTP 200 promptly.
The Onboarding/MIA "Orders" API is for Softpay licences, not transactions. It will not give you transaction data — a common wrong turn.
5. What to store in your reporting database
Store the raw transaction data as you receive it, not just the fields your current report happens to need — requirements always grow. Typically available per transaction:
Your own
RequestId, plus Softpay's transaction identifierTimestamp (with timezone) and final state
Amount, currency, and where applicable tip and surcharge amounts
Card scheme and masked card number
Authorisation code, STAN, batch number
AID — needed if you must distinguish card products such as VPAY or Maestro from their parent scheme
Merchant, store, terminal and Softpay app ID (
Descriptor.appId)For failures: failure code, failure message and origin
Field availability varies between processors and acquirers. Handle missing/null fields gracefully rather than assuming a fixed schema, and test against every processor/acquirer combination in your deployment.
6. Five things that catch people out
Acquirer reports are the financial source of truth. Your POS data proves a payment was attempted and what the terminal saw; the acquirer can still change an outcome afterwards (for example on fraud). Use your own data for operational reporting and reconciliation — settle the books against the acquirer.
The Softpay app only keeps 10 days of history, tied to the current AppID. It is a lookup tool for staff, not a data source for reporting. If nobody stored the data, after 10 days it is gone from the app.
The batch day starts at 03:00 local time, not midnight. Mixing batch boundaries with calendar days is the most common source of "missing" transactions.
Refunds, cancellations and reversals are transactions too. Store them as their own records, linked to the original, or your totals will drift.
Deduplicate on identity, not arrival. Retries, webhook redelivery and recovery lookups will all hand you the same transaction more than once.
7. Implementation checklist
RequestIdgenerated and persisted in the backend before each paymentonFinalimplemented and used as the definitive outcomeTransaction written to your reporting store at final state, idempotent on
RequestIdGetTransactionrecovery path implemented for crashes, kills and connectivity lossNightly batch or Cloud API sweep reconciling yesterday against your own records
Merchant references resolved dynamically — verified with at least two merchants
Report boundaries aligned to the 03:00 batch rollover, or deliberately not
Refunds and cancellations represented in the data model
Reporting output cross-checked against an acquirer report for one full period before go-live
8. References
Developer documentation: Softpay Developer Site · AppSwitch SDK guide · Cloud API · Onboarding (MIA) API