Saudi commerce · Salla · Booking architecture

Salla order reservations: prevent double-booking across systems

A production guide to treating Salla reservations as observations, detecting interval and capacity conflicts, and keeping calendar and ERP projections recoverable.

TOPIC HUBE-commerce Engineering
A real computerized reservation service counter with operators and screens, illustrating operational booking reconciliation.
S

Salla's Order Reservations endpoint gives an integration a read-only view of current order reservations across a date window. That makes it useful for calendar, ERP and operations reconciliation, but it is not an availability engine and it does not by itself prevent two systems from promising the same seat or time slot. The safe pattern is to ingest reservations into a normalized local projection, detect interval and capacity conflicts, publish downstream changes through an idempotent outbox, and repeatedly reconcile that projection with Salla.

This is a practical, documentation-based engineering explainer—not a product announcement or news report. The endpoint, scope and response fields below are documented facts from Salla's official Merchant API pages, verified on October 29, 2026. The normalization model, conflict rules, outbox and reconciliation workflow are engineering recommendations. They are not claims about undocumented Salla behavior.

The answer first

Use GET /admin/v2/reservations with a bounded start and end window and an orders.read token. Store each returned reservation using the merchant and reservation ID as identity, normalize the time interval in the merchant's configured time zone, and retain type, seats_count, the order URL and source timestamps. Feed changes to calendars or an ERP through an outbox, then re-read the same window to detect drift.

Do not treat that list endpoint as a command API. The documented operation retrieves current reservations; it does not document creating a reservation, locking capacity or resolving contention. Availability must have one explicit authority, and every other system should be a projection of that authority.

ConcernRecommended authorityEvidence to retain
Reservation observationSalla Order Reservations read endpointReservation ID, type, start, end, seats and source read time
Sellable capacityThe product or booking system that owns availabilityCapacity version and the decision that accepted the booking
Calendar displayIdempotent external projectionProvider event ID, source reservation ID and last applied digest
ERP workflowERP order/task projectionExternal document ID and source order reference
Drift recoveryScheduled Salla reconciliationWindow cursor, seen IDs, missing-count threshold and result

Start with the documented contract

Salla documents GET https://api.salla.dev/admin/v2/reservations as “List Order Reservations.” The page says the endpoint retrieves current order reservations, requires the orders.read scope, and demonstrates start and end date query parameters. The documented response examples contain:

  • id: reservation identity;
  • title: a display label;
  • type: examples include day and time;
  • start and end: the reservation interval;
  • seats_count: the number of seats in that reservation;
  • url: a dashboard order link in the example;
  • created_at: source creation time.

The page was marked modified on September 7, 2026. Separately, Salla's changelog says Order Details and all order webhooks support product_reservations. That is useful context for event-driven discovery, but it does not turn webhook delivery into a complete historical ledger. Use events to reduce latency and the reservations endpoint to reconcile truth over a bounded window.

The public documentation reviewed here does not state that this endpoint:

  • writes or cancels reservations;
  • guarantees a resource-capacity lock;
  • returns a resource ID suitable for conflict grouping;
  • specifies whether interval bounds are inclusive or exclusive;
  • defines the time-zone offset for every returned timestamp;
  • guarantees that one webhook delivery equals one business transition.

Treat those as integration decisions or unknowns. Confirm merchant and product configuration in a controlled environment before allowing automated downstream actions.

Model observation separately from availability

A common failure is to let three systems believe they own the schedule. A storefront accepts a booking, a shared calendar is edited manually, and an ERP creates a work order. Eventually their states diverge.

Use three explicit layers:

  1. Availability authority: the system that decides whether a seat, technician, room or time slot can be sold.
  2. Reservation observation: the normalized record read from Salla and linked to its order context.
  3. Operational projections: calendar events, ERP tasks, notifications and dashboards derived from the observation.

The calendar should not silently become the authority merely because staff can drag an event. If manual calendar edits matter, route them through a reviewed command path that updates the actual availability owner. Otherwise, overwrite or flag the drift during reconciliation.

Original engineering diagram: Salla reads and webhooks flow through a durable inbox, normalized interval projection, capacity checks and an outbox, with bounded reconciliation. Cover photo by SeekerAlamahgem, CC0 1.0 via Wikimedia Commons; resized or cropped for responsive presentation.
Original engineering diagram: Salla reads and webhooks flow through a durable inbox, normalized interval projection, capacity checks and an outbox, with bounded reconciliation. Cover photo by SeekerAlamahgem, CC0 1.0 via Wikimedia Commons; resized or cropped for responsive presentation. Open for a larger view

Build a stable reservation projection

Keep source data and derived data distinct. A provider-neutral record could be:

{
  "tenant_key": "merchant-42",
  "provider": "salla",
  "reservation_id": "1473353380",
  "reservation_type": "time",
  "title": "Service appointment",
  "start_local": "2026-11-03T10:00:00",
  "end_local": "2026-11-03T10:30:00",
  "source_timezone": "Asia/Riyadh",
  "start_utc": "2026-11-03T07:00:00Z",
  "end_utc": "2026-11-03T07:30:00Z",
  "seats": 1,
  "source_order_url": "redacted-or-access-controlled",
  "source_created_at": "2026-10-29T13:48:33+03:00",
  "observed_at": "2026-10-29T17:05:12Z",
  "source_digest": "sha256:..."
}

The example is an application design, not a Salla payload. Store the merchant time zone from authoritative configuration and reject ambiguous local times rather than guessing. Convert to UTC for comparison, but preserve original local values for audits and customer-facing display.

Use a compound uniqueness key such as (tenant_key, provider, reservation_id). Reservation IDs from different stores must never collide. Compute the digest only from normalized source fields so a repeated read becomes a no-op.

Define interval and capacity conflict rules

Normalize time reservations to half-open intervals: [start, end). Two intervals overlap when:

a.start < b.end AND b.start < a.end

Half-open boundaries allow one booking to end exactly when the next begins. This is a local comparison rule; do not claim it is Salla's undocumented boundary semantics.

Conflict grouping needs a resource key: product, service, room, staff member or capacity pool. The list example does not expose such a key, so derive it only from an authoritative order/product mapping or explicit configuration. Never group merely by title text.

For a capacity pool, sum seats across overlapping active reservations and compare the maximum concurrent total with the configured capacity. A seats_count value of two consumes two units, not one event. If capacity or resource identity is missing, mark the record unclassified and avoid automatic acceptance or cancellation.

Day reservations require a separate policy. Expand them to the merchant's business-day interval, not the integration server's time zone. Handle daylight-saving transitions for merchants outside Saudi Arabia, and never manufacture a 24-hour UTC duration when the local day is shorter or longer.

Combine webhooks with reconciliation

Webhooks are a fast signal, not the only recovery mechanism. Salla's webhook documentation says the receiver must respond within 30 seconds and describes retries when delivery fails. A receiver should therefore authenticate, durably store the raw event, acknowledge quickly, and process asynchronously.

Recommended flow:

  1. Verify the webhook according to Salla's current security guidance.
  2. Persist an immutable inbox record with tenant, event type, source identifiers and payload digest.
  3. Deduplicate by a stable delivery or business key available in the event model.
  4. Enqueue a narrow refresh for the affected order or reservation window.
  5. Upsert the normalized reservation projection.
  6. Create outbox rows for calendar, ERP and notification consumers.
  7. Mark the inbox item complete only after durable state is committed.

Order events that include product_reservations can identify likely changes. Still schedule periodic list reads because events can be delayed, duplicated, unavailable during maintenance or missed before an integration was installed.

Reconcile bounded date windows

Avoid one unbounded “read everything” job. Partition by merchant and date window, and keep checkpoints:

window = [today - lookback, today + horizon]
GET reservations?start=window.start&end=window.end
normalize every returned record
upsert by merchant + reservation_id
mark each returned ID as seen in this run
compare local active records inside the same window
quarantine missing records before declaring deletion
emit outbox changes
advance checkpoint only after commit

The lookback covers late status changes; the forward horizon covers upcoming work. Choose both from business lead times, not an arbitrary global constant. Use a grace rule before treating a missing item as removed: a transient API failure, changed filter semantics or incomplete page must not delete calendar events immediately.

Record the request window, HTTP status, result count, run ID and completion time. If the endpoint times out, the read is safe to retry, but the surrounding job must still be idempotent so it does not duplicate downstream events.

Project to calendars and ERP safely

Create one outbox row per destination and reservation digest. An idempotency key such as tenant:reservation:destination:source_digest makes repeated delivery harmless. Store the destination's event or document ID after success.

When a calendar request times out, the outcome is unknown. Query by the stable external key before creating another event. Do not assume the first request failed. For updates, compare the last applied digest and patch only changed fields. For removals, move through a reversible cancelled/tentative state before hard deletion when the destination supports it.

Keep order dashboard URLs in access-controlled records. Do not place them in public calendar descriptions, analytics labels or error messages. Send only the minimum customer information required by the downstream workflow.

Decision table

SituationSafe actionUnsafe shortcut
Same reservation ID and digestNo-opRewrite every destination
Same ID, changed interval or seatsUpdate projection and outboxCreate a second calendar event
New overlapping reservation below capacityProject normally and record utilizationAssume any overlap is an error
Concurrent seats exceed capacityHold automated confirmation and alert ownerCancel an order based only on local inference
Reservation missing in one readQuarantine and confirm on later read/order detailDelete immediately
Calendar write timed outRead by external key, then decideBlindly create again
Unknown time zone or resourceMark unclassified and stop automationGuess from the integration server

Best practices

  • Give the reservation reader only orders.read.
  • Keep tenant identity in every key, log and checkpoint.
  • Preserve original local timestamps and convert with an explicit IANA time zone.
  • Use half-open intervals consistently in the local conflict engine.
  • Count seats_count against capacity instead of counting rows.
  • Process webhooks through a durable, idempotent inbox.
  • Publish calendar and ERP changes through an outbox with read-after-timeout handling.
  • Reconcile bounded windows and quarantine missing records before removal.
  • Test day, time, boundary, capacity and time-zone cases.
  • Expose metrics for reconciliation age, unclassified records, capacity conflicts and outbox lag.

Anti-patterns and limits

  • Treating the list endpoint as a reservation lock or write API.
  • Using a calendar as a second availability authority.
  • Grouping resources by translated title text.
  • Assuming every reservation consumes exactly one seat.
  • Comparing naive timestamps in the server's local zone.
  • Cancelling an order automatically because one reconciliation read omitted it.
  • Retrying a timed-out calendar create without checking for the first event.
  • Logging bearer tokens, customer data or dashboard URLs.

This design cannot manufacture fields that the provider does not expose. If the integration cannot map a reservation to an authoritative capacity pool, it can still mirror and reconcile the reservation, but it cannot honestly prove that the booking is conflict-free.

Implementation checklist

  1. Confirm the merchant's authoritative time zone and availability owner.
  2. Request only the orders.read scope for the reservation reader.
  3. Fetch a small date window and validate the documented field shapes.
  4. Build the tenant-scoped normalized projection and source digest.
  5. Define resource mappings, half-open intervals and capacity rules.
  6. Add a durable webhook inbox and narrow refresh jobs.
  7. Add an idempotent outbox for calendar and ERP destinations.
  8. Reconcile bounded lookback and future windows.
  9. Quarantine missing and unclassified records for review.
  10. Test retries, duplicates, uncertain writes, time boundaries and multi-seat overlaps.

Related reading: Salla and Zid order-status state machines, sequential Salla order backfills, Salla webhook endpoint rotation, and the E-commerce Engineering hub.

Primary references

Prepared by: Noor Yasser

Official references

These references document the tools discussed. Examples and design decisions are illustrative and should be adapted to the project and its versions.

Prepared by: Noor Yasser

FROM DECISION TO DELIVERY

Working through a similar engineering challenge?

I help teams turn architecture decisions into a clear scope and dependable, reviewable implementation.

Book a 30-minute callRelated serviceBackend engineering & API integrationsRelevant projectLogistics at scale