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 यह है:
- Client-side dedup: हर attempt को unique
client_refके साथ अपने DB में track करें। - Status-check before retry: Timeout पर
GET /api/orders/{id}से verify करें — duplicate बनाने से पहले। - Recent order scan: order_id नहीं पता तो
GET /api/orders/list से identify करें।
यह pattern 99%+ duplicate prevention देता है बिना server-side idempotency keys के। Access request करें और production-ready integration बनाएं।
