Resolving and evidencing a discrepancy from the reconciliationAll articles

Resolving and evidencing a discrepancy from the reconciliation

A reconciliation that finds discrepancies is only half the work. This case shows the other half: decide, give reasons and prove that nothing critical remains open.

Published: 2026-09-12Reading time: 4 mintapinomahub API & workflows
API & processesAPIMarketplaces

The monthly reconciliation reports twelve discrepancies, three of them critical: an order that exists in the channel but not in your system, and two stock levels differing by one piece. Simply adopting the channel figure now removes the discrepancy and keeps the cause.

Resolving and evidencing a discrepancy from the reconciliationInput: a reconciliation reports critical discrepancies between channel and your system 1. Read the reconciliation (GET /commerce/v1/reconciliations/{reconciliationId}): discrepancies with kind, severity and resourceId; plus criticalRemaining 2. Decide (POST /commerce/v1/reconciliations/{reconciliationId}/discrepancies/{discrepancyId}/resolution): apply_source, apply_target or accept_difference, each with a reasonCode 3. Trace the stock (GET /commerce/v1/inventory/ledger): entryType, quantityDelta and balance per entry 4. Re-read the events (GET /commerce/v1/events): events with streamId, sequence and correlationId 5. Reconcile again (POST /commerce/v1/reconciliations): the same period with new checkpoints — criticalRemaining is the figure that counts Output: every discrepancy is decided, reasoned and attributed to an actor accept_difference is a decision, not negligence — it carries a reason and a decisionActorReference.Resolving and evidencing a discrepancy from thereconciliationInput: a reconciliation reports critical discrepancies between channel and your system01Read the reconciliationGET /commerce/v1/reconciliations/{reconciliationId}discrepancies with kind, severity and resourceId; plus criticalRemaining02DecidePOST /commerce/v1/reconciliations/{reconciliationId}/discrepancies/{discrepancyId}/resolutionapply_source, apply_target or accept_difference, each with a reasonCode03Trace the stockGET /commerce/v1/inventory/ledgerentryType, quantityDelta and balance per entry04Re-read the eventsGET /commerce/v1/eventsevents with streamId, sequence and correlationId05Reconcile againPOST /commerce/v1/reconciliationsthe same period with new checkpoints — criticalRemaining is the figure that countsOutput: every discrepancy is decided, reasoned and attributed to an actoraccept_difference is a decision, not negligence — it carries a reason and a decisionActorReference.
Five calls from the reported finding to the new reconciliation. The figure that counts at the end is called criticalRemaining.

The contract therefore makes resolution a decision of its own per discrepancy: adopt the source, adopt the target or explicitly accept the difference — each with a reason and an attributed actor. Resolution is evidenced only when a new reconciliation finds no critical discrepancy any more.

SurfaceRoles
CommerceParts trading, Software vendor, Platform and marketplace

What this case requires

  • A completed reconciliation. The decision refers to a discrepancy with a discrepancyId inside a reconciliation.
  • A person with authority. Adopting source or target changes data; not everyone should be allowed to.
  • Reasons someone else understands. reasonCode is your own code; an in-house catalogue keeps it readable.
  • The will to find the cause. Ledger and event stream can be read; the contract describes no link between their entries and a discrepancy.

The sequence

The table names the responsible call per stage and what exists afterwards. The reasoning for why a stage cannot be skipped follows below it.

The call chain of this use case
StageCallWhat exists afterwards
Read the reconciliationGET /commerce/v1/reconciliations/{reconciliationId}discrepancies with kind, severity and resourceId; plus criticalRemaining
DecidePOST /commerce/v1/reconciliations/{reconciliationId}/discrepancies/{discrepancyId}/resolutionapply_source, apply_target or accept_difference, each with a reasonCode
Trace the stockGET /commerce/v1/inventory/ledgerentryType, quantityDelta and balance per entry
Re-read the eventsGET /commerce/v1/eventsevents with streamId, sequence and correlationId
Reconcile againPOST /commerce/v1/reconciliationsthe same period with new checkpoints — criticalRemaining is the figure that counts

Why each stage is needed

  1. Read the reconciliation. GET /commerce/v1/reconciliations/{reconciliationId} returns counts with matched, discrepant and criticalRemaining, integrity with both sides’ checksums and discrepancies with kind, resourceId, severity and state. Critical ones first: severity distinguishes warning and critical; the contract does not describe what effect a critical discrepancy has.
  2. Decide. POST /commerce/v1/reconciliations/{reconciliationId}/discrepancies/{discrepancyId}/resolution takes decision with apply_source, apply_target or accept_difference, plus reasonCode and expectedRevision. The response names resultingState and decisionActorReference — the decision is attributed to an actor.
  3. Trace the stock. GET /commerce/v1/inventory/ledger shows per entry entryType, quantityDelta and balance. Each entry carries stockItemId; the contract describes no link to a discrepancy.
  4. Re-read the events. GET /commerce/v1/events returns events with streamId, sequence and correlationId. They also carry type, resourceId and occurredAt; the contract does not describe what a gap in sequence means.
  5. Reconcile again. POST /commerce/v1/reconciliations checks the same period with new checkpoints. Resolution is evidenced when criticalRemaining stands at zero; anything else is an assertion.
Decide a discrepancy in favour of the source
curl -X POST \
  -H 'X-Api-Key: <API_KEY>' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: abweichung-2026-08-0003' \
  -d '{"decision":"apply_source","reasonCode":"<reasonCode>","note":"Buchung im Kanal war korrekt, Zustellung fehlte.","expectedRevision":"<revision>"}' \
  'https://commerce-preview.invalid/commerce/v1/reconciliations/<reconciliationId>/discrepancies/<discrepancyId>/resolution'

What you end up with

In the end every discrepancy is decided, reasoned and attributed to an actor, the ledger and the event stream have been read, and a new reconciliation evidences that nothing critical is open.

Where to find this in the documentation

The binding field lists, error codes and sample responses live in this surface’s OpenAPI contract at docs.tapinomahub.com (tapinoma-commerce). All use cases arranged by surface and role: overview of the use cases.

Frequently asked

What is the difference between apply_source and apply_target?

With apply_source the source state applies, with apply_target that of the target. Which side is source and which is target is fixed by the reconciliation’s checkpoints.

May I simply accept a discrepancy?

Yes, with accept_difference — but always with a reason. The decision carries a decisionActorReference and is traceable later.

When is resolution complete?

When a new reconciliation for the same period finds no critical discrepancy any more, that is when criticalRemaining is zero.