Connecting a sales channel without ending up with two writing systemsAll articles

Connecting a sales channel without ending up with two writing systems

The most expensive mistake in a channel integration happens before the first record: two systems both writing. This case shows how authority is settled beforehand.

Published: 2026-09-12Reading time: 5 mintapinomahub API & workflows
API & processesAPIERP & inventoryMarketplacesPricing & valuation

A dealer sells through a marketplace and maintains an ERP alongside. Both systems consider themselves authoritative. Anyone who has lived through it knows the result: inventories that bounce back and forth, prices that are old again a night later, and a unique piece sold twice.

Connecting a sales channel without ending up with two writing systemsInput: a selling account maintained today from both the shop and the ERP 1. Read the capabilities (GET /commerce/v1/capabilities): Per channel: supportLevel, flows and whether reservations are supported 2. Create the connection (POST /commerce/v1/connections): authorizationProof and ownershipMode; credentials are never disclosed 3. Assign the authority (POST /commerce/v1/sync-plans): writerAssignments: at most one active write assignment per sales account, market area, optional offer and flow; conflictPolicy governs conflicts 4. Run it dry (POST /commerce/v1/sync-runs): mode as a preview; counts report read, changed, rejected and conflicted 5. Approve (POST /commerce/v1/sync-runs/{syncRunId}/approval): decision, previewRevision and expectedRevision — what is approved is the reviewed preview, nothing else Output: a connection with settled authority and an approved first transfer Preview: this contract performs no productive channel changes and no fee collection; a separate approval is required.Connecting a sales channel without ending up with twowriting systemsInput: a selling account maintained today from both the shop and the ERP01Read the capabilitiesGET /commerce/v1/capabilitiesPer channel: supportLevel, flows and whether reservations are supported02Create the connectionPOST /commerce/v1/connectionsauthorizationProof and ownershipMode; credentials are never disclosed03Assign the authorityPOST /commerce/v1/sync-planswriterAssignments: at most one active write assignment per sales account, market area,optional offer and flow; conflictPolicy governs conflicts04Run it dryPOST /commerce/v1/sync-runsmode as a preview; counts report read, changed, rejected and conflicted05ApprovePOST /commerce/v1/sync-runs/{syncRunId}/approvaldecision, previewRevision and expectedRevision — what is approved is the reviewed preview,nothing elseOutput: a connection with settled authority and an approved first transferPreview: this contract performs no productive channel changes and no fee collection; a separate approval isrequired.
Five calls to the first approved transfer. The dry run comes before the approval, not after.

The Commerce contract therefore deliberately puts a stage in front of the transfer: before anything is written, a sync plan records who writes; at most one active write assignment is allowed per sales account, market area, optional offer and business flow. Only then does a preview run, and only an explicit approval turns it into a change.

SurfaceRoles
CommerceParts trading, Platform and marketplace, Software vendor

What this case requires

  • An authorised selling account. The connection is created with an authorisation proof; channel credentials are neither disclosed nor passed through.
  • A decision on which system leads. That question is commercial, not technical. The contract only forces it to be answered.
  • Willingness to read the dry run. A preview nobody looks at forfeits the only chance to fail without consequence.
  • An idempotency key per writing call. A repeated call must not have a second effect.

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 capabilitiesGET /commerce/v1/capabilitiesPer channel: supportLevel, flows and whether reservations are supported
Create the connectionPOST /commerce/v1/connectionsauthorizationProof and ownershipMode; credentials are never disclosed
Assign the authorityPOST /commerce/v1/sync-planswriterAssignments: at most one active write assignment per sales account, market area, optional offer and flow; conflictPolicy governs conflicts
Run it dryPOST /commerce/v1/sync-runsmode as a preview; counts report read, changed, rejected and conflicted
ApprovePOST /commerce/v1/sync-runs/{syncRunId}/approvaldecision, previewRevision and expectedRevision — what is approved is the reviewed preview, nothing else

Why each stage is needed

  1. Read the capabilities. GET /commerce/v1/capabilities names supportLevel, flows and reservation support per channel. This stage settles before any work what the channel can do at all — otherwise an integration against an unsupported function fails late and expensively.
  2. Create the connection. POST /commerce/v1/connections takes channelId, channelAccountReference, marketAreaReference, authorizationProof and ownershipMode. Channel-bound details stay behind a private translation boundary; public identifiers are opaque.
  3. Fix the authority. POST /commerce/v1/sync-plans is the decisive stage: writerAssignments allows at most one active write assignment per sales account, market area, optional offer and flow, conflictPolicy governs the dispute, and dryRunRequired can make the dry run binding.
  4. Run it dry. POST /commerce/v1/sync-runs in preview mode returns counts with read, changed, rejected and conflicted. Four figures that say, before the first real write, what would happen.
  5. Approve. POST /commerce/v1/sync-runs/{syncRunId}/approval takes decision, previewRevision and expectedRevision; all three are required fields. What is approved is therefore exactly the reviewed preview — not a state that has since changed.
Start a sync run as a preview
curl -X POST \
  -H 'X-Api-Key: <API_KEY>' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: lauf-2026-09-12-01' \
  -d '{"syncPlanId":"<syncPlanId>","mode":"preview"}' \
  'https://commerce-preview.invalid/commerce/v1/sync-runs'

What you end up with

What remains is a connection where the plan records who writes, and a first transfer read as a preview before approval. The contract does not guarantee that inventory stops bouncing back and forth as a result: it cannot prevent manual work in the channel alongside.

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

Can I let two systems write if they coordinate?

The plan allows at most one active write assignment per sales account, market area, optional offer and flow. What is meant to coordinate can be split across different flows — inventory here, price there, for instance.

Do I always have to run dry?

The plan has a field for it. Setting it makes the dry run binding; that is advisable for first integrations and after plan changes.

Are my marketplace credentials passed on?

No. The connection is created with an authorisation proof, and channel-bound details stay behind a private boundary.