डिजिटल वस्तुओं का थोक मंच

B2B Order API में Duplicate-Safe Ordering 2026: Status-Check Pattern

FoxReload API में Idempotency-Key header नहीं है। Duplicate orders से बचने का सही तरीका: retry से पहले GET /api/orders/{id} status check + client-side dedup। Engineer-level guide।

B2B Order API में Duplicate-Safe Ordering 2026: Status-Check Pattern

FoxReload Public API में Idempotency-Key header नहीं है। इसका मतलब यह नहीं कि duplicate orders inevitable हैं — बस pattern अलग है। यह article वह engineering patterns cover करता है जो FoxReload Orders API (POST /api/orders) को retry-safe बनाते हैं।

1. क्यों single retry दो orders बना सकता है

Simple sequence: आपका ERP POST /api/orders issue करता है। FoxReload order create करता है, delivery start करता है, पर TCP response खो जाती है (network blip)। आपका HTTP client 30s के बाद retry करता है — FoxReload नया request देखता है, दूसरा order बनाता है, balance दूसरी बार debit करता है। Result: duplicate।

Idempotency-Key नहीं है — इसलिए server-side dedup नहीं होगा। Solution: retry से पहले status check।

2. Status-Check Before Retry Pattern

async function createOrderSafe(
  payload: OrderPayload,
  clientRef: string  // आपका internal unique reference
): Promise<Order> {

  // Step 1: क्या पहले से ऑर्डर बना? अपने DB में check करें
  const existing = await db.orderAttempts.findByClientRef(clientRef);
  if (existing?.foxreloadOrderId) {
    // FoxReload पर status verify करें
    const order = await foxreloadGet(`/api/orders/${existing.foxreloadOrderId}`);
    return order; // already exists — return करें, duplicate मत बनाओ
  }

  // Step 2: नया order attempt record करें (UNIQUE constraint से concurrent duplicates रुकेंगे)
  await db.orderAttempts.insert({ clientRef, status: 'pending' });

  try {
    const order = await foxreloadPost('/api/orders', payload);
    await db.orderAttempts.update(clientRef, { foxreloadOrderId: order.id, status: 'created' });
    return order;
  } catch (err) {
    if (isNetworkTimeout(err)) {
      // Order बना या नहीं? Recent orders check करें
      const recentOrders = await foxreloadGet('/api/orders/?limit=5');
      const match = recentOrders.find(o => matchesOurPayload(o, payload));
      if (match) {
        await db.orderAttempts.update(clientRef, { foxreloadOrderId: match.id, status: 'created' });
        return match;
      }
    }
    await db.orderAttempts.update(clientRef, { status: 'failed' });
    throw err;
  }
}

clientRef को request issue करने से पहले DB में persist करें। Retry पर वही ref read करें — नई generate नहीं करें।

3. Client-Side Dedup Storage

// DB schema
CREATE TABLE order_attempts (
  client_ref TEXT PRIMARY KEY,           -- आपका unique reference (e.g., UUIDv4)
  foxreload_order_id TEXT,               -- FoxReload का order UUID (populate होने पर)
  status TEXT NOT NULL DEFAULT 'pending', -- pending | created | failed
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

Storage backends comparison:

Storage Throughput Latency TTL Cost
Redis (SETNX) 200k/s <1ms Custom $0.40/M
Postgres UNIQUE 30k/s 5–8ms $0.10/M
DynamoDB ConditionExpression 100k/s 8–12ms Custom $1.25/M

ज़्यादातर use cases के लिए Postgres UNIQUE index sufficient है — persistent, audit-friendly।

4. Timeout Recovery Flow

async function handleTimeout(clientRef: string, payload: OrderPayload): Promise<Order | null> {
  // Option A: अगर order_id था तो directly check करें
  const attempt = await db.orderAttempts.findByClientRef(clientRef);
  if (attempt?.foxreloadOrderId) {
    return foxreloadGet(`/api/orders/${attempt.foxreloadOrderId}`);
  }

  // Option B: Recent orders scan
  const orders = await foxreloadGet('/api/orders/?limit=10&statuses=active,paid,processing,completed');
  const match = orders.find(o => createdRecently(o) && matchesAmount(o, payload));

  if (match) {
    // Found — record करें और return करें
    await db.orderAttempts.update(clientRef, { foxreloadOrderId: match.id, status: 'created' });
    return match;
  }

  // Order नहीं बना — safe to retry
  return null;
}

FoxReload API Reference

# Order list (recent orders check)
curl "https://public-api.foxreload.com/api/orders/?statuses=active,paid,processing,completed&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

# Specific order check
curl "https://public-api.foxreload.com/api/orders/{order_id}" \
  -H "X-API-Key: YOUR_API_KEY"

Summary

FoxReload API में idempotency keys नहीं हैं — यह Stripe-style feature यहाँ exist नहीं करता। Engineering value यह है:

  1. Client-side dedup: हर attempt को unique client_ref के साथ अपने DB में track करें।
  2. Status-check before retry: Timeout पर GET /api/orders/{id} से verify करें — duplicate बनाने से पहले।
  3. Recent order scan: order_id नहीं पता तो GET /api/orders/ list से identify करें।

यह pattern 99%+ duplicate prevention देता है बिना server-side idempotency keys के। Access request करें और production-ready integration बनाएं।

अक्सर पूछे जाने वाले प्रश्न

FoxReload API में idempotency keys क्यों नहीं हैं?
FoxReload Public API में Idempotency-Key header support नहीं है। Duplicate prevention की ज़िम्मेदारी client पर है। Pattern: हर order attempt को अपने DB में unique client reference के साथ track करें; retry से पहले उस reference से existing order check करें।
Network timeout पर order बना या नहीं — कैसे जानें?
दो तरीके: (1) अगर order_id मिला था तो GET /api/orders/{order_id} call करें। (2) अगर order_id नहीं मिला तो GET /api/orders/?limit=5 से recent orders check करें और अपना order identify करें। Confirm होने के बाद ही नया order बनाएं।
GET requests पर dedup चाहिए?
नहीं। GET definition से safe है — repeat करने से कोई side effect नहीं होता। Dedup सिर्फ POST /api/orders पर चाहिए।
Client-side dedup के लिए storage क्या use करें?
Redis SETNX (fast, TTL support) या Postgres UNIQUE index (persistent, unlimited TTL)। हर attempt create करने से पहले unique client_ref insert करें — duplicate insert fail होगा और पता चल जाएगा कि already exists।
FoxReload API एक्सेस पाएं
पार्टनर सेवावैश्विक सेवाओं के लिए कार्डmarix.cash वर्चुअल कार्ड से ChatGPT, Netflix, Spotify और सैकड़ों सेवाओं का भुगतान करें — तुरंत जारी।कार्ड बनाएं

संबंधित लेख