R
Docs
API Documentation

Idempotency

You can safely retry network failures without double-charging customers or double-creating orders.

1 min read Updated 5/28/2026developer

Why it matters

Networks fail. Servers restart. Your retry logic shouldn't charge the customer twice. Restora 360 guards every mutation that involves money or external side-effects.

Order creation

POST /api/public/[tenantId]/orders is not idempotent by request — but it generates a fresh orderId every time, so a duplicate POST creates a duplicate order. To make it safe, either:

  1. Send an Idempotency-Key header — supported, dedupes by header value for 24 hours.
  2. Or use the payment-intent flow (POST /api/public/[tenantId]/payment-intent) which atomically creates the order and the Stripe PaymentIntent in one call — Stripe's own idempotency then guards subsequent retries.
Shell
curl -X POST \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-7f1a-2025-05-28" \
  -d @order.json \
  https://api.restora360.com/api/public/luigi/orders

Commission ledger

Commission entries are keyed by (sourceInvoiceId, participantId) — replaying a Stripe webhook never double-pays a partner. The same invariant applies to:

  • Designer + sales-agent commission entries (keyed by source-invoice id)
  • Gift-card redemptions (keyed by orderId)
  • Table-bill payments (one open bill per table at a time)
  • Payout batches (keyed by batch id)

Webhook receiver

Every webhook event id is recorded; replay of the same id is a no-op 200. Stripe in particular retries failed deliveries for 3 days; Restora 360 absorbs the repeats safely.

When idempotency is **not** required

Read endpoints (GET) are inherently idempotent. DELETE is idempotent (deleting an already-deleted resource returns 200 / 204, not 404).