Common integration tasks

Test an integration end to end

Fixtures, webhook replay, the idempotency tests most projects skip, and a go-live checklist you can actually hold an integrator to.

An integration that works on the happy path is half an integration. This is the other half — the tests that decide whether a bad night costs ten minutes or a week.

Before you begin. You need a sandbox with fixtures in it, and agreement on who runs each test. "The integrator tested it" is not a result you can act on; ask what they ran and what it produced.

Test with fixtures, not with today's data

A fixture is a record you create deliberately so that a test is repeatable. The alternative — testing against whatever happens to be in the system today — gives you results nobody can reproduce next week.

The fixtures worth having in the sandbox:

FixtureTests
An order in each statusThat the ERP reads pending, placed, in_fulfillment, completed and cancelled correctly
An order with a customer_order_numberThat the buyer's PO number survives into the ERP
An order spanning two cost centresThat per-position data is not dropped
An order with a part-shipped positionThe three statuses disagreeing on purpose
An article sold in packs of 12Quantity and unit handling
An article with a comma decimal priceLocale handling in files
A blocked organizationThat checkout refuses
An organization with an approval thresholdThat an order can legitimately arrive as pending
An article with zero available but positive on_handReservation logic, the classic phantom stock-out
A discontinued article on a saved listConversion behaviour when an article disappears

Build them once, keep them as part of the sandbox seed, and re-create them on every refresh.

The tests most projects skip

Four, and each one corresponds to a real production incident.

1. The idempotency test

What to do: send the same order to the ERP twice — same event, same order number. Then run the same import file twice.

What must happen: one order in the ERP. One set of records after the import, not two, and no error.

This matters because there is no Idempotency-Key header on this platform. Idempotency is a property of your data, not of a request header, and it rests on two things: matching on a stable business key (SKU, customer number, order number — never an internal id), and upserting rather than inserting. Every import should mean "make the record look like this".

The classic failure this catches is a stock file applied as a delta rather than a state. Run it twice and stock is wrong by exactly one night's movements, silently, with nothing in any log.

2. The timeout test

What to do: cut the connection mid-request on a write, or point the integration at an endpoint that accepts the connection and never answers.

What must happen: the integration retries and the result is still one order, not two.

A 429 means nothing happened and is always safe to retry. A timeout tells you nothing about whether the other side processed the request — and that is precisely the case idempotency exists for. An integration that treats those two identically is one that will produce duplicate deliveries.

3. The replay test

What to do: in the webhook's Delivery attempts, redeliver an event the receiver has already processed.

What must happen: the receiver deduplicates on the event id and does nothing. No second order, no error, a 2xx response.

Delivery is at-least-once. The same event will arrive twice eventually, usually on a night when somebody is redeploying the receiver. Then run the negative: replay a delivery with a corrupted signature and confirm the receiver answers 401 and does not process it.

4. The receiver-down test

What to do: stop the receiver for longer than the whole retry window, then bring it back.

What must happen: the platform's delivery log shows the failures, the destination may be disabled automatically, and — the point of the test — your reconciliation run finds the orders that were missed.

If the answer to "what happens to the orders that never arrived?" is a shrug, the integration is missing its safety net. A webhook is the fast path; a scheduled reconciliation is the guarantee. See Common API tasks, by job.

Volume and locale

Two more that catch a specific class of go-live failure:

Run the real volume once. Not 3,000 sandbox products — your actual 400,000. The rate limit is per tenant and shared, and a job that is fine at sandbox size can consume your whole allowance at production size. See Rate limits, quotas and fair use.

Test one file with German-locale numbers. 19,90 read by a system expecting 19.90 produces prices wrong by a factor of a hundred, with no error anywhere. Also test an umlaut in a company name and a ;-separated CSV.

The go-live checklist

Hold the project to this. Every line has a yes/no answer and a name against it.

Access

  • Production keys created, scoped to exactly what the integration uses — not *
  • Secrets stored in a secret manager, not in email, chat or a ticket
  • Key inventory updated: which key, which integration, which owner, who to call
  • Sandbox keys revoked, or scheduled for revocation

Data

  • Field ownership agreed and written down — see Deciding your system of record
  • Import profiles map only the fields the source owns
  • Every match runs on a business key, never an internal id
  • Codes identical between sandbox and production — thread_size, not thread_size_1

Behaviour

  • Idempotency test passed, both directions
  • Timeout test passed
  • Replay test passed, including the bad-signature case
  • Receiver-down test passed, and reconciliation found the gap
  • Retry policy documented: how many attempts, how long, what happens after

Operations

  • Alerts route to a team address, never to a person
  • "No file arrived by 03:00" alarm exists, not only "the run failed"
  • Somebody is named as owner of each integration
  • The runbook says what to do when it breaks at 02:00 on a Sunday
  • X-Request-ID is logged on every call
  • A rollback plan exists: how to stop the integration without stopping the shop

The first week

  • Somebody reads the API and delivery logs daily, not weekly
  • Reconciliation is run manually on day one and compared by hand
  • The first full-volume nightly run is watched by a person
The most expensive go-live failure is a code mismatch. An attribute, list code, channel code or profile code that differs between sandbox and production breaks every mapping at once, on the night, with no useful error. Check the codes against each other before the go-live evening, not during it.

What to check afterwards

For the first two weeks, daily:

  • Error rate by status code — see Monitor your integrations.
  • The webhook failed queue is empty.
  • Reconciliation finds zero missing orders.
  • No integration is retrying constantly and succeeding, which is a limit you are quietly living against.

Next