Salla's order API no longer supports the legacy expanded response. The current List Orders and Order Details documentation says the `expanded=true` contract expired on 1 September 2026; the details endpoint now defaults to the light format. That light response excludes Shipments, Items, Pickup Branch and Customer Groups.
For an ERP, WMS, accounting connector or fulfillment application, this is not a field-renaming exercise. It changes where data is obtained, when it is loaded and how a partial fetch recovers. A connector that previously treated one expanded payload as the complete order aggregate now needs a compact core record plus explicit enrichment steps.
The better design is not to rebuild the old giant payload on every request. Treat the light order as a stable projection for routing and state changes, then hydrate items, shipment or customer context only for workflows that need them. This reduces unnecessary transfer, but it also requires durable jobs, per-resource freshness and reconciliation.
Start with a field-to-owner inventory
Before changing code, record every field the integration consumes and the decision it powers. Separate order-core fields—identity, reference, dates, status, payment, totals and top-level URLs—from resources that no longer arrive inside the light contract. Mark whether each consumer needs the value synchronously, eventually or only for audit.
An ERP sales-order header may need the order ID, reference, currency and totals immediately. A picking list needs items. A shipping label needs shipment and address context. Customer segmentation may need groups, but invoicing probably does not. When these requirements remain mixed in one DTO, the migration recreates expanded mode through a burst of unnecessary calls.
Create separate internal models such as `OrderCore`, `OrderItem`, `FulfillmentContext` and `CustomerContext`. Preserve the remote order ID as the main identity and keep `reference_id` as a searchable business reference. The details documentation permits looking up an order by `reference_id`, but do not use a mutable display value as the database primary key.
Store the raw light response beside the normalized projection for a limited audit period. This makes a schema mismatch diagnosable without making downstream services depend directly on the provider's JSON shape.
Turn hydration into an explicit state machine
When a webhook or reconciliation scan discovers an order, upsert the light core first. Then enqueue only the enrichments required by enabled modules. Salla documents a dedicated List Order Items endpoint at `GET /orders/items?order_id=...` with the `orders.read` scope. Its current notice also deprecates item `codes` and `files` in favor of `data.urls.digital_content`, so a migration should not copy those old arrays into a new contract.
order discovered
-> core_saved
-> items_pending?
-> fulfillment_pending?
-> customer_pending?
-> ready_for_exportGive every enrichment its own status, attempt count, last error, source update time and verified time. An item-fetch failure must not erase a successfully saved order core, and a missing optional customer context must not block a warehouse workflow that only needs items and shipment data. Conversely, do not mark an ERP export complete while a required resource is still pending.
Use an idempotency key such as `store_id + order_id + resource + source_version`. The exact version can be based on a documented update timestamp or on a locally monotonic discovery sequence when the upstream event does not provide a safe version. Serialize writes per order so a delayed enrichment from an older event cannot overwrite a newer state.
Use webhooks as triggers, not complete snapshots
Salla documents ten order webhook events sharing an order model, plus separate shipment-event models. Those events are valuable for low-latency discovery, but the migration should not assume every event is the complete and final aggregate. Persist the event first, acknowledge quickly, then fetch the light details and required resources in background workers.
Deduplicate webhooks by merchant, event type and a stable event or payload identity available to your receiver. Keep the raw body and receipt time, then map it to the order ID. A repeated event should converge to the same state rather than create a second ERP order.
The official troubleshooting guide directs partners to the webhook log and to verify whether the receiver accepted the POST request. That helps distinguish delivery from application failure, but it is not a recovery system. Maintain a dead-letter queue for exhausted jobs and a reconciliation scan that can rediscover orders even when a webhook was missed or rejected.
Respect the sequential pagination contract
The current List Orders documentation imposes unusual pagination rules: request pages sequentially, do not jump from page 1 to page 10, use at most `per_page=30`, complete the sequence within a 15-minute cache window and filter by `from_date` and `to_date` where possible. A page requested out of sequence may return empty.
This means a typical fan-out paginator—where workers fetch pages 2 through 20 in parallel—is the wrong implementation. Keep one cursor owner per merchant and date window. Request page 1, persist its results and checkpoint, then request page 2. If the scan cannot finish safely inside the window, reduce the date range rather than increasing concurrency.
scan key: store + from_date + to_date
checkpoint: next_page + started_at + highest_seen_update
rule: one ordered reader; many downstream enrichment workersSeparate discovery from hydration. The ordered scanner stays lightweight and writes order IDs to a queue; multiple workers may then fetch details and items for different orders, subject to the limits and backoff policy your application has validated. Salla's cited pages do not publish a universal rate-limit number here, so do not hard-code an invented allowance. Measure responses, honor server guidance and make concurrency configurable per merchant.
Use overlapping date windows for recovery—for example, rescan a recent interval and upsert idempotently—rather than trusting one exact boundary. The overlap is a design recommendation, not a platform guarantee. Base the production interval on observed clock behavior, order update patterns and the acceptable recovery delay.
Avoid the N+1 trap with need-based fetches
Replacing every expanded order with four immediate API requests can multiply latency and failure points. Define enrichment profiles. An analytics pipeline may need only the light core. Accounting may require totals and invoice context. Fulfillment needs items and shipment data. Customer engagement may load customer context after the operational export succeeds.
Batch work in the queue by merchant and purpose, cache slowly changing reference data such as known branches separately, and skip a fetch when the stored resource is already fresh enough for the decision. Do not cache order items indefinitely: refunds, edits or fulfillment changes can invalidate them. Record the freshness contract beside each resource.
Monitor requests per discovered order, hydration latency, queue age, incomplete required resources, duplicate events suppressed, reconciliation drift and the percentage of orders exported before all required states are verified. A lower payload size is not a win if the connector silently exports incomplete orders.
Roll out with contract fixtures and shadow comparison
Build fixtures from sanitized light responses, webhook payloads and each enrichment endpoint. Test absent optional objects, an empty item list, reordered items, refunded orders, multiple shipments, a missing pickup branch, timeouts after a successful remote response and a webhook arriving before the detail endpoint reflects the change.
Because expanded mode has already expired, do not design the rollout around a permanent dual read. Instead, compare the new normalized aggregate against stored historical expanded fixtures and against trusted business outputs: ERP headers, totals, item quantities, shipping tasks and accounting records. In a shadow phase, run the new pipeline without allowing it to create external side effects, then diff its results with the current production connector.
Release per merchant or per workflow. Keep a feature flag that can pause enrichment and export independently, and retain a replayable inbox plus durable outbox. Rollback should switch consumers back to the previous internal projection or pause exports; it cannot restore an upstream API contract that Salla no longer serves.
The light order contract forces a healthy architectural boundary. Keep discovery small, make each enrichment intentional, serialize state per order and use Salla's sequential, date-bounded listing rules for recovery. Done well, the connector becomes easier to reason about than the old expanded payload: every resource has an owner, a freshness rule, a failure state and a measurable path to convergence.
Official references
These references document the tools discussed. Examples and design decisions are illustrative and should be adapted to the project and its versions.
- Salla Merchant API — List Orders, verified 27 September 2026
- Salla Merchant API — Order Details, verified 27 September 2026
- Salla Merchant API — List Order Items, verified 27 September 2026
- Salla Merchant API — Orders webhook models, verified 27 September 2026
- Salla Platform Docs — Webhook troubleshooting, verified 27 September 2026
Prepared by: Noor Yasser
Working through a similar engineering challenge?
I help teams turn architecture decisions into a clear scope and dependable, reviewable implementation.




