# ReconProof - Invoice & Payment Reconciliation (`zahi90/reconproof`) Actor

Match structured invoice and payment records, including split and grouped payments. Get proposed matches, ambiguity flags, unmatched records and arithmetic checks in JSON. Human review required. No bank connection or PDF extraction.

- **URL**: https://apify.com/zahi90/reconproof.md
- **Developed by:** [Zahi Mansour](https://apify.com/zahi90) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $250.00 / 1,000 reconciliation reports

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## ReconProof — Auditable Payment & Ledger Matching

Compare two **already structured** transaction exports. Get reviewable one-to-one, split-payment, combined-payment and optionally bounded many-to-many matching proposals, with arithmetic, source pointers, alternative assignments and unmatched records.

**An optimum is not proof of payment.** ReconProof does not authenticate statements, post ledger entries, make payments, certify accounts or identify fraud. Every proposal requires review. Only submit data you are authorized to process; use pseudonymous IDs and counterparty keys rather than names, account numbers or credentials.

### When an AI agent should use this tool

Use ReconProof after an authorized workflow has extracted and mapped invoice, payment or ledger records into the documented JSON format. Use it when the workflow needs consistent arithmetic and a global matching analysis, including a way to identify competing explanations.

Do not use it to download statements, read PDFs, parse arbitrary CSV, infer tax treatment, invent fees or connect to banking services. No generative-model API or bank credentials are required.

The initial product is a bounded analysis service, not an enterprise reconciliation system.

### What makes the analysis useful

- **Exact amount comparisons:** decimal inputs are converted to integer minor units. Group totals and residuals are never decided using floating-point equality.
- **Global assignment:** a transaction can appear in at most one selected group. The optimizer chooses across the whole connected candidate set, rather than accepting the first locally attractive pair.
- **Alternative-match testing:** for every selected group, the engine bans that group and solves the component again. A same-coverage alternative with a sufficiently similar evidence score means the proposal is labelled ambiguous.
- **Split and combined payments:** supported group sizes are up to three records on each side. Both sides grouped simultaneously require explicit opt-in.
- **Audit trail:** every proposed group contains row IDs, JSON pointers, original and normalized minor-unit amounts, totals, residuals, date spans, evidence and caveats.
- **Post-solve checks:** no row reuse, permitted grouping, source pointers, exact totals, record partition and conservation equations are recalculated without running the solver again.

The optimization is a binary integer-selection model solved by SciPy/HiGHS. The solver uses numerical methods; this is **not a formal mathematical proof certificate**. Amount eligibility is checked with integers before optimization. The post-solve checker validates arithmetic and assignments, not solver optimality or real-world truth.

### Quick example

One invoice for GBP 1,200 and two receipts for GBP 700 and GBP 500 share the same counterparty key and are within the date window. ReconProof can propose a one-to-many match and show:

```text
120000 minor units = 70000 + 50000
Residual = 0
```

A different case has one GBP 250 invoice and two otherwise identical GBP 250 receipts. The tool selects an illustrative assignment, flags it as `ambiguous`, provides a competing assignment, and leaves the other receipt unmatched in the illustrated solution. That unmatched receipt is **not** declared invalid, duplicated or fraudulent.

### Input

Provide `left` and `right`, each containing 1–100 records. `options` is optional. One run compares one pair of datasets and returns one report.

```json
{
  "left": [
    {"id":"INV-1","amount":"1200.00","currency":"GBP","date":"2026-09-01","scope":"company-a-account-1","partyKey":"customer-42","reference":"INV-1"}
  ],
  "right": [
    {"id":"PAY-1","amount":"700.00","currency":"GBP","date":"2026-09-02","scope":"company-a-account-1","partyKey":"customer-42","reference":"INV-1"},
    {"id":"PAY-2","amount":"500.00","currency":"GBP","date":"2026-09-03","scope":"company-a-account-1","partyKey":"customer-42","reference":"INV-1"}
  ],
  "options": {"maxGroupSize":3,"rightSign":"same","amountToleranceMinorUnits":0}
}
```

#### Record fields

| Field | Meaning |
|---|---|
| `id` | Required unique ID within the side; 80-character maximum. Whitespace and Unicode presentation are normalized. |
| `amount` | Required nonzero canonical decimal **string**. `"1000.25"` is valid. `"1,000.25"`, symbols, exponent notation and floating-point JSON numbers are rejected. Integer JSON numbers are accepted as whole major units. |
| `currency` | Required supported uppercase three-letter code. No conversion between currencies. |
| `date` | Required valid ISO date, `YYYY-MM-DD`. The caller must decide which comparable dates to use. |
| `scope` | Required reconciliation partition, e.g. company/account/book. Different normalized scopes never match. |
| `partyKey` | Optional exact shared counterparty identifier. Use pseudonymous keys. Required for every grouped match. Known conflicting party keys block matching. |
| `reference` | Optional invoice/payment identifier. Case and whitespace normalized; punctuation retained. |

Unknown fields are rejected. Duplicate normalized IDs on one side are rejected. Economically identical rows with different IDs are preserved and warned about, not deleted.

A scope or party key is trusted only as caller-supplied data; ReconProof does not authenticate it. Partition independent bank accounts, subsidiaries, currencies and accounting books correctly before submission.

#### Matching policy

| Option | Default | Supported values |
|---|---:|---|
| `dateWindowDays` | 14 | Integer 0–90. Maximum full-group date span, not business days or asymmetric settlement lags. |
| `maxGroupSize` | 3 | Integer 1–3. Set 1 to disable split/group search. |
| `allowManyToMany` | false | Allow groups on both sides, up to `maxGroupSize` on each. |
| `allowAmountOnly` | false | Allow singleton pairs without identity evidence. Such results carry a warning and still require review. Never overrides known party conflicts. |
| `amountToleranceMinorUnits` | 0 | Integer 0–1000, applied separately in each currency's minor units. Any residual remains visible; it is not classified as a fee or tax. |
| `ambiguityMargin` | 5 | Integer 0–200. Evidence-score loss permitted for an alternative with equal record coverage in the same component. Zero still catches equal-score ties. |
| `rightSign` | same | `same` or `opposite`. The latter explicitly multiplies right-side amounts by -1 for comparisons. |
| `currencyScales` | supported defaults | Optional mapping of additional three-letter codes to integer decimal precision 0–4. Supported currency scales cannot be changed. |

Supported defaults: GBP, USD, EUR, CAD, AUD, NZD, CHF, SEK, NOK, DKK, PLN, CZK, RON, BRL, MXN, ZAR, INR, SGD, HKD, CNY, AED, SAR and ILS use 2 decimals; JPY and KRW use 0; KWD, BHD, OMR, JOD and TND use 3. This is a documented product configuration, not a complete currency registry.

Zero amounts are excluded. Positive and negative rows are not netted into a group. Maximum magnitude per row is 10^14 minor units. A row is consumed whole; allocating only part of one record is not supported.

### What the optimizer prioritizes

The primary objective is **maximum number of records covered by allowed nonoverlapping groups**. Among equal-coverage solutions it maximizes a heuristic evidence score. It does not maximize monetary value or estimated recovery.

For each candidate, the score starts with 100 for a shared normalized reference, 50 for a shared party key, and 40 for an exact amount total. It subtracts up to 30 points for the date span and five points for each grouped row beyond a simple pair, with a floor of zero. These are transparent policy weights, **not calibrated probabilities**.

This coverage-first policy may prefer explaining more rows to a smaller number of individually stronger matches. Tighten scope and identity data before relying on a result. The output always requires review.

All uniqueness and ambiguity statements refer to the **generated candidates, supplied records and selected policy only**. Other real-world explanations, omitted rows or larger groups may exist. Equal-score illustrative assignments may differ between solver versions.

### Output

One dataset item is the complete report. Important fields:

- `summary`: record, candidate, selected-group, ambiguity and unmatched counts.
- `matches`: proposed groups, exact calculations, evidence and alternative assignments.
- `unmatched`: rows not in the illustrated solution, distinguishing no generated candidate from competition for another assignment.
- `ledgerTotals`: separate totals per scope/currency, with the conservation equation checked.
- `effectivePolicy`: the applied options and limits.
- `components`: solver status and objective within each generated conflict component.
- `integrity`: post-solve arithmetic and assignment checks.
- `inputFingerprint` and `reportFingerprint`: hashes for reproducibility; not source authentication, signatures or proof of truth.
- `humanReviewRequired`: always true.

A match's assessment is `ambiguous` or `unique_within_configured_model`. Neither means the transaction was independently confirmed or approved for posting.

`status: analysis_complete` means the bounded computation and exclusion tests finished. It does not mean every financial record has a match.

`STATUS` in the run's key-value store contains delivery/error diagnostics. The complete commercial result is in the default dataset.

### Limits and failure behavior

The initial version accepts up to 100 rows per side. Group search permits at most 12 rows per side in a same-party/scope/currency/sign bucket, up to 2,500 candidate matches, up to 40 records and 700 candidates in one connected conflict component, and approximately 25 seconds of solver-analysis time. Generation and overhead add time. The Actor should use a 120-second run timeout for initial tests.

When these limits or unresolved solver statuses prevent full analysis, the tool fails explicitly without requesting the report fee. It does **not** silently discard candidates and then claim a unique result. Narrow the batch or set `maxGroupSize` to 1; do not split interdependent records merely to force a desired match.

### Pricing and delivery

The custom event is `reconciliation-report`: one complete, delivered report for one bounded input pair. The proposed launch test price is **$0.25 per report**, but the Store Pricing tab is authoritative.

A complete report is billable when it finds ambiguous matches or no matches. You pay for the completed analysis, not a guaranteed recovery or match rate.

Invalid input, complexity-limit failures and unfinished solver checks do not request the report event. A separately listed Actor-start charge may still apply.

The implementation checks remaining event budget before analysis and uses Apify's event-aware dataset delivery. The positive automatic dataset-item fee must be removed to avoid duplicate result charges. Repeated delivery of an existing result within the **same run** is not requested again. A new run is a new analysis and can be billed again.

After an uncertain delivery timeout, the code checks the run's dataset. If delivery still cannot be established, it stops rather than blindly recharging. This is not an unconditional exactly-once billing guarantee. Inspect the run and billing records before retrying an uncertain outcome.

### Privacy and security

The application does not connect to bank accounts, fetch URLs, scrape private sources, execute input as code, or forward records to a language-model API. It does not log raw transaction data in custom status messages.

**Apify still processes and may retain Actor inputs, datasets, logs and key-value records according to platform/account settings.** This is not zero-retention or local-only processing. Use authorized, minimized and pseudonymized data. Hashes and references can still be sensitive. Do not publish real customer inputs or outputs in example tasks or support issues.

Review applicable contractual, privacy and retention requirements before offering the service to real customers. The product does not provide accounting, audit, tax, legal or payment-approval advice.

### Automated use

Call the Actor with the same input shape through the Apify API, SDK or compatible agent tooling. Agent callers should set explicit spending limits and request only authorized analyses. Platform discovery and payment eligibility are separate from the algorithm and are not a promise of customer demand.

The correct workflow is: extract and map records → request analysis → inspect proposals and ambiguity → have an authorized process or person decide what to do. Do not automatically move money based on this report.

### Development and testing

The project includes synthetic examples, a unittest suite, exhaustive small-graph oracle comparisons and an offline report verifier.

```bash
python -m unittest discover -s tests -v
python scripts/offline_demo.py
python scripts/verify_report.py examples/01_demo.json examples/expected_01_demo.json
```

The local tests are not a real financial audit or live Apify billing validation. Run private platform tests and inspect the actual charged events before publication.

### Support

Use the Actor's Issues area for a synthetic reproduction and run ID where appropriate. Never post real invoices, bank details, personal data, credentials or sensitive reports in a public issue.

# Actor input Schema

## `left` (type: `array`):

1-100 records with id, decimal-string amount, currency, ISO date and scope. Add partyKey/reference for identity evidence.

## `right` (type: `array`):

1-100 comparable records. Same partyKey must mean the same party. Choose rightSign opposite only when your bookkeeping convention requires it.

## `options` (type: `object`):

Optional policy object. Exact amounts by default. maxGroupSize 1-3. Grouped matches require matching partyKey and bounded pools. See README for all limits and the coverage-first objective.

## Actor input object example

```json
{
  "left": [
    {
      "id": "INV-100",
      "amount": "1000.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-a",
      "reference": "INV-100"
    },
    {
      "id": "INV-200",
      "amount": "1200.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-b",
      "reference": "INV-200"
    },
    {
      "id": "INV-301",
      "amount": "300.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-c"
    },
    {
      "id": "INV-302",
      "amount": "200.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-c"
    },
    {
      "id": "INV-400",
      "amount": "250.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-d"
    }
  ],
  "right": [
    {
      "id": "PAY-100",
      "amount": "1000.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-a",
      "reference": "INV-100"
    },
    {
      "id": "PAY-201",
      "amount": "700.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-b",
      "reference": "INV-200"
    },
    {
      "id": "PAY-202",
      "amount": "500.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-b",
      "reference": "INV-200"
    },
    {
      "id": "PAY-300",
      "amount": "500.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-c"
    },
    {
      "id": "PAY-401",
      "amount": "250.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-d"
    },
    {
      "id": "PAY-402",
      "amount": "250.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-d"
    }
  ],
  "options": {
    "dateWindowDays": 14,
    "maxGroupSize": 3,
    "allowManyToMany": false,
    "allowAmountOnly": false,
    "amountToleranceMinorUnits": 0,
    "ambiguityMargin": 5,
    "rightSign": "same"
  }
}
```

# Actor output Schema

## `reports` (type: `string`):

One complete reviewable analysis per dataset row. Inspect matches, alternatives, unmatched rows and ledgerTotals.

## `status` (type: `string`):

Budget, error and recovery status; not a payment receipt.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "left": [
        {
            "id": "INV-100",
            "amount": "1000.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-a",
            "reference": "INV-100"
        },
        {
            "id": "INV-200",
            "amount": "1200.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-b",
            "reference": "INV-200"
        },
        {
            "id": "INV-301",
            "amount": "300.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-c"
        },
        {
            "id": "INV-302",
            "amount": "200.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-c"
        },
        {
            "id": "INV-400",
            "amount": "250.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-d"
        }
    ],
    "right": [
        {
            "id": "PAY-100",
            "amount": "1000.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-a",
            "reference": "INV-100"
        },
        {
            "id": "PAY-201",
            "amount": "700.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-b",
            "reference": "INV-200"
        },
        {
            "id": "PAY-202",
            "amount": "500.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-b",
            "reference": "INV-200"
        },
        {
            "id": "PAY-300",
            "amount": "500.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-c"
        },
        {
            "id": "PAY-401",
            "amount": "250.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-d"
        },
        {
            "id": "PAY-402",
            "amount": "250.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-d"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zahi90/reconproof").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "left": [
        {
            "id": "INV-100",
            "amount": "1000.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-a",
            "reference": "INV-100",
        },
        {
            "id": "INV-200",
            "amount": "1200.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-b",
            "reference": "INV-200",
        },
        {
            "id": "INV-301",
            "amount": "300.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-c",
        },
        {
            "id": "INV-302",
            "amount": "200.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-c",
        },
        {
            "id": "INV-400",
            "amount": "250.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-d",
        },
    ],
    "right": [
        {
            "id": "PAY-100",
            "amount": "1000.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-a",
            "reference": "INV-100",
        },
        {
            "id": "PAY-201",
            "amount": "700.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-b",
            "reference": "INV-200",
        },
        {
            "id": "PAY-202",
            "amount": "500.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-b",
            "reference": "INV-200",
        },
        {
            "id": "PAY-300",
            "amount": "500.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-c",
        },
        {
            "id": "PAY-401",
            "amount": "250.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-d",
        },
        {
            "id": "PAY-402",
            "amount": "250.00",
            "currency": "GBP",
            "date": "2026-09-01",
            "scope": "example-ledger",
            "partyKey": "customer-d",
        },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("zahi90/reconproof").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "left": [
    {
      "id": "INV-100",
      "amount": "1000.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-a",
      "reference": "INV-100"
    },
    {
      "id": "INV-200",
      "amount": "1200.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-b",
      "reference": "INV-200"
    },
    {
      "id": "INV-301",
      "amount": "300.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-c"
    },
    {
      "id": "INV-302",
      "amount": "200.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-c"
    },
    {
      "id": "INV-400",
      "amount": "250.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-d"
    }
  ],
  "right": [
    {
      "id": "PAY-100",
      "amount": "1000.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-a",
      "reference": "INV-100"
    },
    {
      "id": "PAY-201",
      "amount": "700.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-b",
      "reference": "INV-200"
    },
    {
      "id": "PAY-202",
      "amount": "500.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-b",
      "reference": "INV-200"
    },
    {
      "id": "PAY-300",
      "amount": "500.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-c"
    },
    {
      "id": "PAY-401",
      "amount": "250.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-d"
    },
    {
      "id": "PAY-402",
      "amount": "250.00",
      "currency": "GBP",
      "date": "2026-09-01",
      "scope": "example-ledger",
      "partyKey": "customer-d"
    }
  ]
}' |
apify call zahi90/reconproof --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zahi90/reconproof"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dFDBrc7GWb5uOAVzv/builds/G0jO9kZ5EF0eMJcen/openapi.json
