Skip to main content

Overview

After placing an order, poll the /checkOrder endpoint to track status and retrieve card codes when fulfilled. Most orders process within seconds.
Poll every 5-10 seconds until order reaches a final state: FULFILLED, PARTIALLY_FILLED, or REFUNDED.

API Reference

GET /v3/gift-cards/checkOrder/{orderId}

Complete endpoint documentation

Order Status Values

Order is processing. Continue polling. Most orders resolve within 30 seconds.
Success! All cards delivered. fulfilled_quantity === quantity. Cards available in cards array.
Partial success. Some cards delivered, rest cancelled. fulfilled_quantity < quantity. Partial refund issued automatically.
Failed. Order completely failed. fulfilled_quantity === 0. Full refund issued automatically.

Sandbox Testing

Use sandbox mode to test without spending real balance:

Test Failed Order

Use TEST_REFUND as type ID → Simulates failed order (REFUNDED status)

Test Partial Success

Use TEST_PARTIAL as type ID → Simulates 50% fulfillment (PARTIALLY_FILLED status)
Sandbox Example
// Test different scenarios without real charges
const testScenarios = [
  {
    productId: "507f1f77bcf86cd799439011",
    typeId: "TEST_REFUND", // Will fail and refund
    quantity: 2,
  },
  {
    productId: "507f1f77bcf86cd799439011",
    typeId: "TEST_PARTIAL", // Will deliver 50% of cards
    quantity: 4,
  },
];

// Place test order
const order = await placeOrder(
  testScenarios[0].productId,
  testScenarios[0].typeId,
  testScenarios[0].quantity
);

// Poll for results
const result = await pollOrderUntilComplete(order.orderId);
console.log("Test result:", result.status);

Basic Status Check

async function checkOrderStatus(orderId) {
  const response = await fetch(
    `https://api.oneclickdz.com/v3/gift-cards/checkOrder/${orderId}`,
    {
      headers: {
        "X-Access-Token": process.env.API_KEY,
      },
    }
  );

  if (!response.ok) {
    throw new Error(`Failed to check order: ${response.status}`);
  }

  const result = await response.json();
  return result.data;
}

// Usage
const orderId = "6901616fe9e88196b4eb64b3";
const order = await checkOrderStatus(orderId);

console.log(`Status: ${order.status}`);
console.log(`Quantity: ${order.quantity}`);

if (order.cards) {
  console.log(`Cards delivered: ${order.cards.length}`);
}

Response Examples

Handling (Processing)

{
  "success": true,
  "data": {
    "_id": "6901616fe9e88196b4eb64b3",
    "status": "HANDLING",
    "quantity": 2,
    "product": "507f1f77bcf86cd799439011",
    "type": "type_001",
    "time": "2025-10-29T01:00:00.000Z"
  }
}

Fulfilled (Success)

{
  "success": true,
  "data": {
    "_id": "6901616fe9e88196b4eb64b3",
    "status": "FULFILLED",
    "quantity": 2,
    "fulfilled_quantity": 2,
    "fulfilled_amount": 980,
    "price_per_card": 490,
    "cards": [
      {
        "value": "XXXX-XXXX-XXXX-XXXX",
        "serial": "123456789"
      },
      {
        "value": "YYYY-YYYY-YYYY-YYYY",
        "serial": "987654321"
      }
    ],
    "time": "2025-10-29T01:00:00.000Z"
  }
}

Partially Filled

{
  "success": true,
  "data": {
    "_id": "6901616fe9e88196b4eb64b3",
    "status": "PARTIALLY_FILLED",
    "quantity": 5,
    "fulfilled_quantity": 3,
    "fulfilled_amount": 1470,
    "price_per_card": 490,
    "cards": [
      {
        "value": "AAAA-AAAA-AAAA-AAAA",
        "serial": "111111111"
      },
      {
        "value": "BBBB-BBBB-BBBB-BBBB",
        "serial": "222222222"
      },
      {
        "value": "CCCC-CCCC-CCCC-CCCC",
        "serial": "333333333"
      }
    ],
    "time": "2025-10-29T01:00:00.000Z"
  }
}

Simple Polling Implementation

async function pollOrderUntilComplete(orderId, maxAttempts = 60) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    console.log(`Checking order status (${attempt}/${maxAttempts})...`);

    const order = await checkOrderStatus(orderId);

    // Order is complete
    if (["FULFILLED", "PARTIALLY_FILLED", "REFUNDED"].includes(order.status)) {
      console.log(`Order completed: ${order.status}`);
      return order;
    }

    // Wait 5 seconds before next check
    if (attempt < maxAttempts) {
      await new Promise((resolve) => setTimeout(resolve, 5000));
    }
  }

  throw new Error("Order still processing after timeout");
}

// Usage
try {
  const order = await pollOrderUntilComplete("6901616fe9e88196b4eb64b3");

  if (order.status === "FULFILLED") {
    console.log("Success! Cards:", order.cards);
  } else if (order.status === "PARTIALLY_FILLED") {
    console.log(
      `Partial delivery: ${order.fulfilled_quantity}/${order.quantity}`
    );
  } else {
    console.log("Order failed and refunded");
  }
} catch (error) {
  console.error("Error:", error.message);
}

Handling Different Results

function handleOrderResult(order) {
  switch (order.status) {
    case "FULFILLED":
      console.log(`✅ Success: ${order.fulfilled_quantity} cards delivered`);
      console.log(`Cost: ${order.fulfilled_amount} DA`);

      // Process each card
      order.cards.forEach((card, index) => {
        console.log(`Card ${index + 1}: ${card.value}`);
        // Encrypt and deliver to customer
      });
      break;

    case "PARTIALLY_FILLED":
      console.log(
        `⚠️ Partial: ${order.fulfilled_quantity}/${order.quantity} cards`
      );
      console.log(`Charged: ${order.fulfilled_amount} DA`);

      const refund =
        (order.quantity - order.fulfilled_quantity) * order.price_per_card;
      console.log(`Refunded: ${refund} DA`);

      // Deliver available cards
      order.cards.forEach((card) => {
        console.log(`Delivered: ${card.value}`);
      });
      break;

    case "REFUNDED":
      console.log("❌ Order failed - full refund issued");
      break;
  }
}

Complete Polling Example

async function processOrder(productId, typeId, quantity) {
  try {
    // 1. Place order
    console.log("Placing order...");
    const order = await placeOrder(productId, typeId, quantity);
    console.log(`Order placed: ${order.orderId}`);

    // 2. Poll for completion
    console.log("Waiting for fulfillment...");
    const result = await pollOrderUntilComplete(order.orderId);

    // 3. Handle result
    handleOrderResult(result);

    return result;
  } catch (error) {
    console.error("Order processing failed:", error.message);
    throw error;
  }
}

// Usage
await processOrder("507f1f77bcf86cd799439011", "type_001", 2);

Best Practices

Poll Every 5 Seconds

Balance between responsiveness and API load

Set Timeout

Stop polling after 5 minutes (60 attempts)

Handle All States

Process FULFILLED, PARTIALLY_FILLED, and REFUNDED

Test First

Use sandbox mode with TEST_REFUND and TEST_PARTIAL

Next Steps