> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.crisscross.money/settlement-reporting/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.crisscross.money/_mcp/server. # Settlement Reporting CrissCross produces a structured **settlement report** at the time of each settlement, delivered alongside the wire. Every report ties one bank credit you receive back to the individual transactions — collections, refunds, payouts, fees, FX, and adjustments — that produced it, so you can reconcile against your own ledger. The reporting model is built on one guarantee: > **One file = one SubMID = one settlement = one wire.** Each settlement produces exactly one report, sharing a single `Settlement ID` with the wire it accompanies. There is no wire without a file, and no file without a wire. > **Info** > > Settlement reports are available through **two delivery channels — API and SFTP** — and you choose which one per SubMID. See [Delivery channels](#delivery-channels). ## MID and SubMID Settlement is organised around a two-level merchant hierarchy. Understanding it is the key to reading a settlement report, because every report is scoped to a single SubMID. | Term | Meaning | Example | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- | | **MID** (Merchant ID) | The parent merchant account — your company as a whole. Groups one or more SubMIDs and is how CrissCross identifies you as a legal entity. | `Acme` | | **SubMID** (Sub-Merchant ID) | A child account under a MID, scoped to a **single market / processing currency**. Each SubMID settles independently, on its own cadence, and produces its own files and wires. | `AcmeKES`, `AcmeNGN` | A single MID typically has several SubMIDs — one per currency it collects in: **`Merchant hierarchy`** ```text title="Merchant hierarchy" Acme ← MID (parent merchant) ├── AcmeKES (KES → USD) ← SubMID, settles in USD ├── AcmeNGN (NGN → USD) ← SubMID, settles in USD └── AcmeZAR (ZAR → USD) ← SubMID, settles in USD ``` Because a SubMID is scoped to one processing currency, **settlement always happens per SubMID**: `AcmeKES` and `AcmeNGN` settle separately, each on its own schedule, each producing a distinct file and wire. > **Note** > > Each SubMID carries an account code (for example `M1002345`) that appears in the file name and in the file's `Merchant Account` field. See [How MID and SubMID appear in the file](#how-mid-and-submid-appear-in-the-file). ## How settlement works The settlement engine runs on each SubMID's configured cadence (its **settlement delay**, e.g. `T+2`, is a per-SubMID property). For each cycle: #### Batch transactions Collect every transaction for the SubMID since the last settlement event that is in scope for this cycle. #### Compute net Apply the rolling net model (below) to derive the settlement amount in the processing currency. #### Apply the FX rate Convert each transaction into the settlement currency (typically USD) at its **all-in rate** — the mid-market rate plus the agreed spread. When a transaction was priced by a [rate lock](/rate-locks) it settles at that locked rate, so lines in one file can carry different rates; each line records its `All In Rate`, `Rate Lock ID`, and when the lock was struck (`Rate Lock Created At`). The header `Settlement Rate` is the amount-weighted average of these per-line rates across the settlement. #### Send the wire The wire is sent with the payment reference `MID:{merchant_id}|STL:{settlement_id}`, so you can match the credit on your bank statement to the report. #### Generate the report The file is produced atomically with the wire, sharing the same `Settlement ID`, and delivered via the SubMID's configured channel. > **Note** > > Settlements are only produced when there is activity. A cycle with no in-scope transactions generates **no file and no wire**. ### The settlement model The net settlement amount is a rolling net, computed per SubMID per cycle: ``` NetSettlementAmount = (collections + refund_returned + payout_reversed + positive_adjustments + reserve_releases) − (refunds + payouts + negative_adjustments + reserve_holds) − processing_fees ``` Fees are **netted internally** on both inflows and outflows: * **Collections** — the customer pays `Gross`. `Net = Gross − Fee`, and you receive `Net`. * **Refunds / payouts** — the customer or beneficiary receives the full requested amount; the fee is an *additional* deduction from your balance. `Gross` is shown negative, `Fee` positive, and `Net = Gross − Fee`. Each line carries its **gross in the processing currency** and its **net already converted to the settlement currency** at that transaction's all-in rate — so the sum of the line `Net` values equals the header `Net Settlement Amount`, and the wire, with no further conversion. In the totals, `Gross Total` is in the processing currency while `Fees Total` and `Net Settlement Amount` are in the settlement currency; each total names its own currency. ## The settlement report file * **Format:** CSV, UTF-8, in a custom **multi-section** layout: the HEADER and LINE sections carry different columns, so the file is not one uniform table. Within each section, field quoting and escaping follow [RFC 4180](https://www.rfc-editor.org/rfc/rfc4180). * **Structure:** self-describing. Every row starts with a `Record Type` column — a settlement-level **HEADER** row followed by N transaction **LINE** rows. Each section is preceded by its own field-name row, so the file can be parsed without an external schema. * **Naming:** `{SubMID}_{SettlementEndDate:YYYYMMDD}_{ProcessingCurrency}_{SettlementID}.csv` — the date token is the **`Settlement End Date`** of the period the file covers. **`Example file name`** ```text title="Example file name" M1002345_20260416_NGN_STL000123456.csv ``` Reading the name: SubMID account `M1002345`, settlement period ending `2026-04-16`, processing currency `NGN`, settlement `STL000123456`. ### Header fields Every header field describes the settlement as a whole. Monetary totals are in the **settlement currency**. | Field | Description | | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Record Type` | `HEADER` for this row. | | `Settlement ID` | Unique identifier — 1:1 with this file and the wire. | | `Company Account` | The MID — the parent merchant (HQ). | | `Merchant Account` | The SubMID account code — constant across the file, scoped to one processing currency. | | `Merchant Name` | Display name of the SubMID entity. | | `Settlement Start Date` | Start of the period this settlement covers (ISO 8601, UTC). | | `Settlement End Date` | End of the period this settlement covers — when the funds are settled, and the date used in the file name (ISO 8601, UTC). | | `Processing Currency` / `Settlement Currency` | e.g. `NGN` / `USD`. | | `Settlement Rate` | The **amount-weighted average** of the per-line `All In Rate` values across the settlement, each line weighted by its absolute `Gross` — `Σ(\|Gross\| × All In Rate) ÷ Σ\|Gross\|` — in processing units per 1 settlement unit (e.g. `1577.02`, i.e. \~1 USD = 1577 NGN), inclusive of spread. Because lines can each settle at their own locked rate, this is a blend; the per-line `All In Rate` is authoritative for each transaction, so reconcile from the line `Net` values rather than by applying this rate to the gross total. | | `Gross Total` / `Gross Total Currency` | Sum of line gross, in the **processing** currency. | | `Fees Total` / `Fees Total Currency` | Sum of processing fees, in the **settlement** currency. | | `Net Settlement Amount` / `Net Settlement Amount Currency` | The wired amount, in the **settlement** currency. | | `Transaction Count` | Total number of `LINE` rows in the file. | #### How MID and SubMID appear in the file The two-level hierarchy maps onto the file's columns as follows: | Concept | File field | Example value | | ------------------------- | ------------------ | ------------- | | **MID** (parent merchant) | `Company Account` | `Acme` | | **SubMID** (account code) | `Merchant Account` | `M1002345` | | **SubMID** (display name) | `Merchant Name` | `AcmeNGN` | All three are settlement-level and appear on the `HEADER` row only. A file covers exactly one SubMID, so repeating them on every `LINE` would restate a constant. ### Line fields Each line represents one transaction. `Gross` is in the **processing currency** and is signed (`+` inflow, `−` outflow). `Initiation Amount`, `Processing Fee`, and `Net` are in the **settlement currency**. | Field | Description | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Record Type` | `LINE` for a transaction row. | | `Session ID` | Session identifier for the customer journey. | | `PSP Reference` | CrissCross transaction ID. | | `Merchant Reference` | Your own reference, if supplied on the transaction. | | `Original PSP Reference` | Populated for `REFUND`, `REFUND_RETURNED`, `PAYOUT_REVERSED`, `CHARGEBACK`. | | `Payment Method` | `CARD` / `BANK_TRANSFER` / `MOBILE_MONEY` / `WALLET` / `ADJUSTMENT` / `RESERVE`. | | `Creation Date` | ISO 8601 timestamp (UTC). | | `Gross` / `Gross Currency` | Amount in the **processing** currency (signed: `+` inflow, `−` outflow). | | `Initiation Amount` / `Initiation Currency` | `Gross` converted to the **settlement** currency at this line's `All In Rate`. `Initiation Currency` — the currency you initiated in — always equals the `Settlement Currency`. | | `Processing Fee` / `Fee Currency` | Fee in the **settlement** currency (always a positive deduction). | | `All In Rate` | The all-in rate applied to this line (processing → settlement, inclusive of spread). Reflects the transaction's rate lock when one applied, so it can differ line to line. | | `Rate Lock Created At` | ISO 8601 (UTC) — when the rate lock backing this line was struck. Empty when no lock applied. | | `Rate Lock ID` | The `rlk_` [rate lock](/rate-locks) applied to this transaction, if any. | | `Net` / `Settlement Currency` | `Initiation Amount − Processing Fee` — both sides already in the **settlement** currency. | | `Transaction Type` / `Transaction Status` | See the [enumerations](#transaction-types) below. | | `Acquirer` / `Acquirer Reference` | Processing-side identifiers. | | `Payer ID` | Payer or beneficiary identifier. | | **Card-only fields** | Populated when `Payment Method = CARD`, empty otherwise: `Card Scheme`, `Card Last4`, `Card BIN`, `Card Country`, `Card Funding Type`, `Issuer Name`, `Issuer Country`, `Authorisation Code`, `ARN`, `3DS Status`, `MCC`. | | `Chargeback Reference` / `Chargeback Reason Code` | Reserved; empty until chargebacks are in scope. | | `Metadata` | Free-form `key=value;key=value`. | ### Transaction types | Code | Meaning | Gross sign | | ---------------------------------------------------------- | --------------------------------------------------------- | :--------: | | `COLLECTION` | Inbound customer payment | `+` | | `REFUND` | Outbound to a customer who previously paid | `−` | | `REFUND_RETURNED` | Refund that failed and was returned | `+` | | `PAYOUT` | Outbound to a beneficiary not tied to a prior collection | `−` | | `PAYOUT_REVERSED` | Payout that bounced and was returned | `+` | | `ADJUSTMENT` | Manual correction (carries a mandatory `Metadata` reason) | `±` | | `RESERVE_HOLD` / `RESERVE_RELEASE` | Withholding / release of a reserve | `−` / `+` | | `CHARGEBACK` / `CHARGEBACK_REVERSAL` / `SECOND_CHARGEBACK` | Reserved — not yet in scope | n/a | ### Transaction statuses `AUTHORISED`, `CAPTURED`, `SALE`, `SETTLED`, `REVERSED`, `REFUNDED`, `RETURNED`. Lines in a settlement file are typically in a terminal state. ### Example file An abbreviated report for SubMID `AcmeNGN` (`M1002345`), settling `NGN → USD`. `Gross` is in the processing currency (NGN); the `Net`, fees, and totals are in the settlement currency (USD). Every row is tagged with `Record Type`. Card-only columns, `Session ID`, `Rate Lock Created At`, and other fields are present in the real file but omitted here for readability. **`M1002345_20260416_NGN_STL000123456.csv`** ```csv title="M1002345_20260416_NGN_STL000123456.csv" Record Type,Settlement ID,Company Account,Merchant Account,Merchant Name,Settlement Start Date,Settlement End Date,Processing Currency,Settlement Currency,Settlement Rate,Gross Total,Gross Total Currency,Fees Total,Fees Total Currency,Net Settlement Amount,Net Settlement Amount Currency,Transaction Count HEADER,STL000123456,Acme,M1002345,AcmeNGN,2026-04-14T00:00:00Z,2026-04-16T00:00:00Z,NGN,USD,1577.02,185400,NGN,3.75,USD,113.25,USD,3 Record Type,PSP Reference,Merchant Reference,Original PSP Reference,Payment Method,Creation Date,Gross,Gross Currency,Initiation Amount,Initiation Currency,Processing Fee,Fee Currency,All In Rate,Rate Lock ID,Net,Settlement Currency,Transaction Type,Transaction Status,Payer ID LINE,TX_9a1b2c3d,ORDER-55001,,CARD,2026-04-14T08:12:44Z,150000,NGN,94.94,USD,2.37,USD,1580,rlk_550e8400-e29b-41d4-a716-446655440001,92.57,USD,COLLECTION,SETTLED,PAYER_7781 LINE,TX_9a1b2c3e,ORDER-55002,,MOBILE_MONEY,2026-04-14T13:47:02Z,85400,NGN,54.05,USD,1.35,USD,1580,rlk_550e8400-e29b-41d4-a716-446655440001,52.70,USD,COLLECTION,SETTLED,PAYER_7782 LINE,TX_9a1b2c3f,ORDER-54980,TX_88f0aa12,CARD,2026-04-15T10:03:19Z,-50000,NGN,-31.99,USD,0.03,USD,1563,rlk_550e8400-e29b-41d4-a716-446655440005,-32.02,USD,REFUND,REFUNDED,PAYER_7601 ``` Reconciliation check: the line `Net` values are already in the settlement currency, so they sum directly — `92.57 + 52.70 − 32.02 = 113.25 USD` — to the `Net Settlement Amount`, the exact amount of the wire. Because each line settles at its own locked rate (the refund here used `1563`, the collections `1580`), you reconcile by summing the per-line `Net`, not by applying the header `Settlement Rate` to the gross total. The header `Settlement Rate` (`1577.02`) is the amount-weighted average of the line rates, so it sits between them and won't reproduce any single line exactly. ## Delivery channels Reports are available through **two channels**, configured per SubMID with one channel designated as primary. #### SFTP Download the file from the CrissCross SFTP server, where it appears at settlement time. Best for finance teams that consume files rather than call an API. #### API pull Poll the settlement endpoints for new settlements, then pull one — as JSON or as the CSV file — from the API. ### SFTP CrissCross hosts an SFTP server. Your reports appear there shortly after each settlement is produced, and you connect and download them on your own schedule. CrissCross does not connect out to a server of yours, so there is no inbound access for you to open. Authentication is by SSH key. You generate the key pair and send us the public half — **CrissCross never needs, and will never ask for, your private key.** Access is also restricted by source IP, so we need the addresses you will connect from before your account will work. #### Getting set up #### Generate a key pair ```bash ssh-keygen -t ed25519 -f ~/.ssh/crisscross_sftp -C "acme-settlement-reports" ``` This writes two files: `crisscross_sftp` (your private key — keep it secret) and `crisscross_sftp.pub` (the public key). #### Send us the public key Send the **contents of `crisscross_sftp.pub`** to your CrissCross contact, through whichever channel you already use with us, naming the MID and SubMIDs it is for. It is a single line beginning `ssh-ed25519`. A public key is not sensitive, so it needs no special handling. Send only the `.pub` file — if you are ever asked for the other one, it is not us. #### Send us the IP addresses you'll connect from We allowlist them, so a connection from anywhere else is refused before authentication is even attempted. A short list of individual addresses is best. A CIDR range works if your connections leave from a pool, but keep it as narrow as you can — an allowlist is only worth as much as the range is specific. **Tell us before these change.** An address that has not been allowlisted cannot connect at all, which looks like the server being down rather than a permissions problem. #### Receive your connection details We reply with the server address, your username, and the server's **host key fingerprint**. You get one username per environment — see [Sandbox and live](#sandbox-and-live). #### Connect and verify the fingerprint ```bash sftp -i ~/.ssh/crisscross_sftp @ ``` On the first connection your client shows the server's fingerprint. **Check it matches the one we sent you before accepting it.** If it does not match, stop and contact support — do not continue. #### What you'll find Each username lands directly in its own directory, holding that environment's settlement reports. You cannot see anything above it, and no other merchant can see yours. **`A listing`** ```text title="A listing" sftp> ls M1002345_20260316_NGN_STL000123401.csv M1002345_20260331_NGN_STL000123478.csv M1002345_20260416_NGN_STL000123456.csv ``` File names follow the convention described under [The settlement report file](#the-settlement-report-file), so the SubMID, period end date, processing currency, and `Settlement ID` are all readable without opening the file. A file is **complete the moment it appears in the listing** — there is no partially written state, and no temporary extension to filter out. If you can see it, you can download it. #### Downloading ```bash # One file sftp> get M1002345_20260416_NGN_STL000123456.csv # Everything, into the current local directory sftp> mget *.csv ``` Access is **read-only**. You can list and download; you cannot delete, rename, or move files, so the common *download-then-delete* and *move-to-processed* patterns will fail. Track what you have already processed by file name instead. A `Settlement ID` is unique and never reused, so a file name you have already seen is a settlement you have already handled. Files remain available after you download them, which also means you can re-fetch any past settlement at any time without asking us to resend it. #### Sandbox and live Sandbox and live reports are delivered to **separate accounts, never the same directory**. You receive one username per environment: | Environment | Contains | | ------------------ | ------------------------------------- | | `_live` | Real settlements, matching real wires | | `_sandbox` | Sandbox settlements only | Each key you send us can be enrolled against either or both. Keeping them separate means a sandbox file can never be picked up by a process reconciling real money. #### Timing A report appears within a minute or two of its settlement being produced. That settlement's [`transaction.settled`](/core-concepts-webhooks) webhooks are sent at the moment of production, so they arrive **before the file is there** — treat them as the earliest point worth looking, not as confirmation that the report has landed. A connection made the instant the first webhook arrives can legitimately find an empty directory, so retry for a few minutes before treating the report as missing. If you would rather not track webhooks, connecting on a schedule works just as well — reports stay in the directory, so nothing is lost by checking late. Settlements are only produced when there is activity, so a cycle with no in-scope transactions leaves nothing new to collect. #### Host key changes Pin the fingerprint we give you. We will contact you in advance if it ever has to change. A fingerprint that changes without notice should be treated as a failed connection, not accepted — tell us instead. ### API pull When a settlement is produced, you'll receive a [`transaction.settled`](/core-concepts-webhooks) webhook for each transaction it covers. The endpoints below retrieve the settlement itself — call them in response to those events, or poll on your own schedule: | Endpoint | Purpose | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `GET /settlements` | List your settlements, newest first. Filter by `settlementStartDate`, `settlementEndDate`, `processingCurrency`, and `settlementCurrency`. Cursor-paginated with `limit` and `cursor`. | | `GET /settlements/{id}` | Return the header and lines as JSON, mirroring the CSV one-to-one. | | `GET /settlements/{id}/file` | Return the CSV file body as a `text/csv` download. | > **Note** > > There is currently **no settlement-level webhook** — nothing fires once per settlement batch, on either channel. To pick up settlements one at a time rather than one event per transaction, check for new ones on your own schedule: either list the SFTP directory or poll `GET /settlements`. > > The settlement API is being rolled out per merchant. If you need programmatic access or SFTP delivery configured for a SubMID, contact [support@crisscross.money](mailto:support@crisscross.money). > Reconcile settled funds to source transactions with per-SubMID settlement reports, delivered via API or SFTP