Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.crbtrack.com/llms.txt

Use this file to discover all available pages before exploring further.

What is Idempotency?

Idempotency ensures that making the same API request multiple times produces the same result as making it once. This is critical for:
  • Network failures: Retry safely without creating duplicates
  • Timeouts: Resubmit requests that timed out
  • Distributed systems: Handle concurrent requests

How It Works

Include an idempotencyKey in your POST requests:
{
  "idempotencyKey": "order-12345-abc",
  ...
}
If you send the same key within 24 hours:
  1. The system recognizes the duplicate
  2. Returns the original response without re-executing
  3. No duplicate resources are created

Implementation

Generate Unique Keys

Use a consistent strategy for generating keys:
// Option 1: Use your order ID
const idempotencyKey = `order-${orderId}`;

// Option 2: UUID
const idempotencyKey = crypto.randomUUID();

// Option 3: Composite key
const idempotencyKey = `${customerId}-${orderId}-${timestamp}`;

Example: Safe Order Creation

async function createOrder(order) {
  // Key based on your order ID ensures idempotency
  const idempotencyKey = `create-order-${order.id}`;
  
  try {
    const response = await fetch('https://api.crbtrack.com/api/v1/orders/create', {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        idempotencyKey,
        ...orderData
      })
    });
    
    const data = await response.json();
    return data;
    
  } catch (error) {
    // Safe to retry - same idempotencyKey won't create duplicate
    if (shouldRetry(error)) {
      return createOrder(order);  // Same key = same result
    }
    throw error;
  }
}

Idempotency Rules

  • Length: 8-64 characters
  • Characters: Alphanumeric, hyphens, underscores
  • Uniqueness: Must be unique per operation type
  • Expiry: Keys expire after 24 hours
  • Keys are scoped to your API key (not global)
  • Same key can be used for different endpoints
  • Example: order-123 for /orders/create is different from order-123 for /orders/void
  • First request: Operation executes, response cached
  • Duplicate request: Cached response returned (HTTP 200)
  • Different payload, same key: Error returned (409 Conflict)

Endpoints Supporting Idempotency

EndpointidempotencyKey
POST /api/v1/orders/createRequired
POST /api/v1/manifests/submitOptional
POST /api/v1/orders/voidRequired
POST /api/v1/labels/{id}/reprintRequired

Common Patterns

Pattern 1: Order ID as Key

Best for e-commerce integrations:
const idempotencyKey = `order-${order.id}`;
✅ Simple and predictable
✅ Natural deduplication if order already processed
✅ Easy to debug

Pattern 2: Request Hash

Best for operations without natural IDs:
const idempotencyKey = crypto
  .createHash('sha256')
  .update(JSON.stringify(requestBody))
  .digest('hex')
  .substring(0, 32);
✅ Automatically detects identical requests
⚠️ Different results for slightly different payloads

Pattern 3: Timestamp + ID

Best for retry-heavy workflows:
const idempotencyKey = `${customerId}-${action}-${Date.now()}`;
⚠️ Generates new key on each attempt
⚠️ Doesn’t prevent accidental duplicates

Handling Conflicts

If you send a different payload with the same key:
{
  "success": false,
  "error": {
    "code": "IDEMPOTENCY_CONFLICT",
    "message": "Request payload differs from original request with this idempotencyKey"
  }
}
Resolution: Generate a new unique key for the modified request.

Best Practices

Do

  • Use predictable keys (order IDs)
  • Store keys with requests for debugging
  • Retry with same key on failures

Don't

  • Generate random keys per retry
  • Reuse keys for different operations
  • Rely on idempotency for business logic