Reconciliation & Reporting

Overview

This skill enables AI agents and applications to manage reconciliation workflows, payment beneficiaries, and financial reporting using Eclipse APIs.

It supports:

  • Querying individual reconciliation results and aggregate daily/weekly summaries
  • Updating reconciliation result statuses (IGNORED, REMATCH) and adding comments
  • Creating, listing, updating, and deleting payment beneficiaries
  • Generating pre-defined financial reports and running ad-hoc SQL reads

1. Reconciliation

Trigger: "run reconciliation", "check recon", "show unmatched transactions", "reconcile transactions"

Required inputs: tenantId, date range

1.1 Query Reconciliation Results

Retrieve individual reconciliation results, optionally filtered by status.

GET {baseUrl}/rest/v1/recons/results
    ?tenantId={tenantId}
    &dateFromIncl=2026-05-18T00:00:00.000Z
    &dateToExcl=2026-05-19T00:00:00.000Z
    &status=UNMATCHED
    &limit=50
    &offset=0
Authorization: Bearer {jwt}

Response:

[
  {
    "reconResultId": 1028374,
    "tenantId": 42,
    "institutionId": "7",
    "transactionDate": "2026-05-18T14:30:00.000Z",
    "difference": 750.00,
    "currency": "ZAR",
    "status": "UNMATCHED",
    "matchType": "AMOUNT_DATE",
    "recordType": "TX",
    "description": "No matching counterpart record found",
    "comment": "",
    "created": "2026-05-18T14:30:05.000Z",
    "recordA": {
      "reconRecordId": 7741,
      "recordType": "TX",
      "transactionDate": "2026-05-18T14:30:00.000Z",
      "transactionAmount": 750.00,
      "transactionCurrency": "ZAR",
      "normalisedAmount": 750.00,
      "normalisedCurrency": "ZAR",
      "internalUniqueId": "wdr-00001234",
      "externalUniqueId": "ext-ref-abcd",
      "dataSourceLocation": "wallet-service",
      "dataSourceId": 3,
      "matchingHint": "750.00|2026-05-18"
    },
    "recordB": null
  }
]

recordA is the Eclipse-side record. recordB is the external (e.g. bank statement) counterpart — null when no match has been found.

status filter values: MATCHED, UNMATCHED, IGNORED, REMATCH.

recordType filter values: TX (transaction-level), SUM (summary-level), BAL (balance-level).

1.2 Get Reconciliation Summary

Retrieve aggregate reconciliation statistics for a time period.

GET {baseUrl}/rest/v1/recons/summaries
    ?tenantId={tenantId}
    &aggregation=DAY
    &dateFromIncl=2026-05-18T00:00:00.000Z
    &dateToExcl=2026-05-19T00:00:00.000Z
Authorization: Bearer {jwt}

aggregation values: HOUR, DAY, WEEK, MONTH (default: DAY).

Response:

[
  {
    "timeBucket": "2026-05-18",
    "matchType": "AMOUNT_DATE",
    "recordType": "TX",
    "status": "MATCHED",
    "totalDifference": 0.00,
    "currency": "ZAR",
    "count": 1478,
    "tenantId": 42,
    "institutionId": "7"
  },
  {
    "timeBucket": "2026-05-18",
    "matchType": "AMOUNT_DATE",
    "recordType": "TX",
    "status": "UNMATCHED",
    "totalDifference": 1099.99,
    "currency": "ZAR",
    "count": 4,
    "tenantId": 42,
    "institutionId": "7"
  }
]

The summary returns one row per timeBucket / matchType / recordType / status combination. To assess the overall match rate for a day, compare the count on MATCHED rows against UNMATCHED rows.

1.3 Update a Reconciliation Result

Operators can update the status or add a comment to a recon result — for example, to mark a record as IGNORED after manual investigation, or to flag it as REMATCH for re-processing.

PUT {baseUrl}/rest/v1/recons/results/{reconResultId}
Authorization: Bearer {jwt}
Content-Type: application/json
{
  "status": "IGNORED",
  "comment": "Confirmed duplicate entry from upstream feed — safe to exclude"
}
FieldRequiredDescription
statusYesNew status: MATCHED, UNMATCHED, IGNORED, or REMATCH
commentNoFree-text note recorded against the result for audit purposes

Response: The full updated ReconResult object.

Requires Recon.UPDATE.Allowed permission.

API Reference: GET /recons/results · GET /recons/summaries · PUT /recons/results/{id}


2. Beneficiary Management

Trigger: "add beneficiary", "create payment destination", "add bank account", "manage beneficiaries"

Required inputs: full bank account details for creation

Beneficiaries are saved bank accounts or mobile money destinations used when initiating payments and withdrawals.

2.1 Create Beneficiary

POST {baseUrl}/rest/v1/beneficiaries
Authorization: Bearer {jwt}
Content-Type: application/json
{
  "walletId": 1092847,
  "accountHolderName": "Nomsa Khumalo",
  "bankName": "ABSA",
  "branchCode": "632005",
  "bankAccountNumber": "987654321",
  "accountType": "SAVINGS",
  "reference": "Loan repayment",
  "provider": "RTC"
}

Response:

{
  "beneficiaryId": 4829104,
  "walletId": 1092847,
  "accountHolderName": "Nomsa Khumalo",
  "bankName": "ABSA",
  "bankAccountNumber": "987654321",
  "branchCode": "632005",
  "accountType": "SAVINGS",
  "reference": "Loan repayment",
  "provider": "RTC",
  "status": "ACTIVE",
  "created": "2026-05-19T10:00:00.000Z"
}

2.2 List Beneficiaries

GET {baseUrl}/rest/v1/beneficiaries
    ?walletId={walletId}
    &limit=20
    &offset=0
Authorization: Bearer {jwt}

Additional filter query params: customerId, organisationId, bankAccountNumber, mobileNumber.

2.3 Get a Beneficiary

GET {baseUrl}/rest/v1/beneficiaries/{beneficiaryId}
Authorization: Bearer {jwt}

2.4 Update Beneficiary

PUT {baseUrl}/rest/v1/beneficiaries/{beneficiaryId}
Authorization: Bearer {jwt}
Content-Type: application/json
{ "beneficiaryId": 4829104, "reference": "Updated reference — June 2026" }

2.5 Delete Beneficiary

DELETE {baseUrl}/rest/v1/beneficiaries/{beneficiaryId}
Authorization: Bearer {jwt}

Returns 204 No Content on success.

Notes

  • bankName is a free-text string — common values: ABSA, STANDARD_BANK, FNB, NEDBANK, CAPITEC.
  • accountType values: CURRENT, SAVINGS, TRANSMISSION.
  • provider values: RTC (near-instant), DTB (same-day), EFT (1–2 business days). Availability depends on tenant configuration.
  • status values: ACTIVE, BLOCKED, PENDING, REJECTED.
  • onlyCheck: true validates the bank account via AVS without creating a beneficiary record.
  • saveOnPass: true creates the beneficiary only if AVS validation passes.

API Reference: POST /beneficiaries · GET /beneficiaries · PUT /beneficiaries/{id} · DELETE /beneficiaries/{id}


3. Report Generation

Trigger: "generate report", "run report", "get report data", "export transaction report"

Required inputs: reportId for pre-defined reports; sqlQuery for ad-hoc reads

3.1 Retrieve a Pre-defined Report

Pre-defined report IDs are configured per tenant. Parameters are positional — the report template maps s1s20 (string), n1n8 (number), and d1d8 (date) slots to its own named inputs. Ask the platform administrator which report IDs and parameter slots are available.

GET {baseUrl}/rest/v1/reports/{reportId}
    ?tenantId={tenantId}
    &s1={stringParam1}
    &n1={numberParam1}
    &d1={dateParam1}
    &format=json
Authorization: Bearer {jwt}
ParameterDescription
s1s20String parameters (up to 20)
n1n8Numeric parameters (up to 8)
d1d8Date parameters (up to 8, ISO 8601)
tenantIdTenant to scope the report to
organisationIdOptional organisation scope
formatOutput format: json (default), csv, xml, xls
streamResultBoolean — stream large result sets
deliveryMechanismTypeOptional delivery method (e.g. email)
deliveryMechanismValueValue for the delivery method (e.g. email address)

Response: JSON array (or file in CSV/XLS format) shaped by the report template. The exact fields depend on the report definition.

3.2 Run an Ad-hoc Read

Ad-hoc reads execute a raw SQL query against the platform database. This endpoint is intended for platform administrators and trusted internal tooling only.

POST {baseUrl}/rest/v1/reports/adhoc/reads
Authorization: Bearer {jwt}
Content-Type: application/json
{
  "sqlQuery": "SELECT wallet_id, balance, currency FROM wallet WHERE tenant_id = 42 AND status = 'ACTIVE' LIMIT 100",
  "connectionName": "eclipse_sandbox",
  "description": "Active wallet balances for tenant 42"
}

Response: JSON string containing the query results.

3.3 Run an Ad-hoc Update

Execute a raw SQL update or insert. Restricted to platform administrators.

POST {baseUrl}/rest/v1/reports/adhoc/updates
Authorization: Bearer {jwt}
Content-Type: application/json
{
  "sqlQuery": "UPDATE wallet SET status = 'BLOCKED' WHERE wallet_id = 99999",
  "connectionName": "eclipse_sandbox",
  "description": "Block wallet 99999 per ops request"
}

Response:

{ "rowsAffected": 1 }

Notes

  • Pre-defined report IDs are configured per tenant — consult the platform administrator for available report IDs and their parameter mappings.
  • Ad-hoc read/update endpoints are admin-only — do not surface them to end users.
  • Report data may contain PII — apply appropriate access controls when handling report output.

API Reference: GET /reports/{reportId} · POST /reports/adhoc/reads · POST /reports/adhoc/updates


Common Patterns for AI Agents

1. Daily Reconciliation Review

  1. Fetch reconciliation summary for the previous day:
    GET /rest/v1/recons/summaries?tenantId=42&aggregation=DAY&dateFromIncl=2026-05-18T00:00:00Z&dateToExcl=2026-05-19T00:00:00Z
  2. Check if any row has status=UNMATCHED with count > 0 — this indicates unresolved transactions.
  3. Fetch detailed results for investigation:
    GET /rest/v1/recons/results?tenantId=42&status=UNMATCHED&dateFromIncl=2026-05-18T00:00:00Z&dateToExcl=2026-05-19T00:00:00Z
  4. For each unmatched result, review recordA (the Eclipse-side record) against the bank statement:
    • If it is a known duplicate or safely excludable: PUT with status: "IGNORED" and a comment explaining the reason.
    • If it requires re-running the matching algorithm: PUT with status: "REMATCH".
  5. Re-run the summary to confirm the unmatched count has reduced.

2. Pre-payment Beneficiary Check

Before initiating an EFT withdrawal, check whether a beneficiary already exists:

  1. GET /rest/v1/beneficiaries?walletId={walletId} to list existing beneficiaries
  2. Match by bankAccountNumber
  3. Only create a new beneficiary if no match is found — avoid duplicates

3. Report Execution

  1. Ask the platform administrator for the available reportId values and which parameter slots (s1s20, n1n8, d1d8) each report uses.
  2. Call GET /rest/v1/reports/{reportId} with the appropriate parameter values and format=json (or csv for download).

Error Handling

[
  {
    "type": "BUSINESS",
    "severity": "LOW",
    "description": "Recon result not found",
    "code": "REC001",
    "traceId": "3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d",
    "spanId": "1a2b3c4d5e6f7a8b",
    "environment": "eclipse-sandbox"
  }
]
HTTP StatusMeaningCommon Cause
400Bad requestInvalid date format, missing required field
401UnauthorisedJWT missing, expired, or malformed
403ForbiddenCaller role does not have reconciliation or reporting permissions
404Not foundResource ID does not exist or belongs to a different tenant

When a traceId is present in an error response, always surface it to the user — it is the primary identifier for diagnosing the failure.


Best Practices

  • Always apply date bounds on reconciliation queries — unbounded queries on large datasets can time out.
  • Use limit and offset pagination on all list endpoints. Default to limit=20.
  • Use ISO 8601 datetime with explicit UTC timezone on all date parameters: 2026-05-19T00:00:00.000Z.
  • Reconciliation status updates should only be performed by an authorised operator. Always record the reason in the comment field for the audit trail.
  • Report data may contain PII — handle row data with appropriate access controls.
  • When a traceId is returned in an error, record it and reference it in any support escalation.

Permissions Required

Recon.READ.Allowed
Recon.UPDATE.Allowed