Starship Rewards API

Get Order Details API

Retrieve comprehensive order information with decrypted voucher codes for delivered orders

Get Order Details API

Retrieve detailed information for a specific order, including decrypted voucher codes when the order has been delivered.

Endpoint

GET /api/v1/orders/{id}

Authentication: Bearer token required

Request Headers

Authorization: Bearer <access_token>

Path Parameters

ParameterTypeRequiredDescription
idintegerYesOrder ID (must be > 0)

Response

Success Response

Status Code: 200 OK

Response Body:

{
  "id": 12345,
  "reference_code": "ORD-ABC123",
  "transaction_id": 789,
  "amount": "25.00",
  "product_id": 1001,
  "denomination": "25.00",
  "quantity": 1,
  "discount": "0.00",
  "vouchers": [
    {
      "claim_url": "https://redeem.example.com/abc123xyz",
      "card_number": "1234567890123456",
      "voucher_reference_number": "REF-VOUCHER-123",
      "pin_code": "1234",
      "expires_at": "2025-12-31T23:59:59Z"
    }
  ],
  "status": "delivered",
  "placed_at": "2024-01-15T10:30:00Z"
}

Response Fields

Order Fields

FieldTypeDescription
idintegerUnique order identifier
reference_codestringUnique order reference for tracking
transaction_idintegerAssociated payment transaction ID
amountstringTotal order amount (2 decimal places)
product_idintegerProduct catalog identifier
denominationstringUnit value (2 decimal places)
quantityintegerNumber of units ordered
discountstringApplied discount amount
vouchersarrayVoucher details (only when delivered)
statusstringCurrent order status
placed_atstringOrder timestamp in RFC3339 format

Voucher Fields

FieldTypeDescription
claim_urlstring | nullURL for voucher redemption (for gift links)
card_numberstring | nullDecrypted card/voucher number
voucher_reference_numberstring | nullDecrypted voucher reference
pin_codestring | nullDecrypted PIN code
expires_atstringVoucher expiration date (RFC3339)

Voucher Availability by Status

Orders progress through different statuses, with voucher data becoming available based on the current status:

StatusDescriptionWallet DeductionVouchers Available
PENDINGOrder created, processing in progressYes (Deducted)No (Not yet)
PROCESSINGOrder currently being fulfilledYes (Deducted)No (Not yet)
DELIVEREDOrder completed successfullyYes (Deducted)Yes (Available)
PARTIALLY_DELIVEREDSome vouchers deliveredYes (Deducted)Partial (Some available)
FAILEDOrder processing failedNo (Refunded)No (None)
CANCELLEDOrder was cancelledNo (Refunded)No (None)

Status Flow:

Order Creation → PENDING → PROCESSING → DELIVERED

                 FAILED (if processing fails)

Important: Voucher codes are only decrypted and returned when the order status is DELIVERED or PARTIALLY_DELIVERED. For other statuses, the vouchers array will be empty.

Security Features

Encryption

All sensitive voucher data is encrypted at rest:

  • Voucher codes are stored using AES-256 encryption
  • Decryption only occurs when order status is DELIVERED
  • PIN codes and reference numbers are separately encrypted

Examples

# Get order details
curl -X GET "{{host}}/api/v1/orders/12345" \
  -H "Authorization: Bearer your_access_token"

# Get order and extract vouchers (using jq)
curl -X GET "{{host}}/api/v1/orders/12345" \
  -H "Authorization: Bearer your_access_token" \
  | jq '.vouchers'

# Check order status
curl -X GET "{{host}}/api/v1/orders/12345" \
  -H "Authorization: Bearer your_access_token" \
  | jq '.status'

# Get voucher codes securely
curl -s -X GET "{{host}}/api/v1/orders/12345" \
  -H "Authorization: Bearer your_access_token" \
  | jq -r '.vouchers[] | "Card: \(.card_number) PIN: \(.pin_code)"'
<?php
// Get order details with vouchers
function getOrderDetails($api, $orderId) {
    try {
        $order = $api->makeAuthenticatedRequest(
            "{{host}}/api/v1/orders/{$orderId}"
        );

        return $order;

    } catch (Exception $e) {
        error_log("Failed to get order {$orderId}: " . $e->getMessage());
        throw $e;
    }
}

// Display order with vouchers
function displayOrderWithVouchers($api, $orderId) {
    $order = getOrderDetails($api, $orderId);

    echo "<div class='order-details'>\n";
    echo "  <h2>Order #{$order['id']}</h2>\n";
    echo "  <div class='order-info'>\n";
    echo "    <p><strong>Reference:</strong> {$order['reference_code']}</p>\n";
    echo "    <p><strong>Transaction:</strong> #{$order['transaction_id']}</p>\n";
    echo "    <p><strong>Product ID:</strong> {$order['product_id']}</p>\n";
    echo "    <p><strong>Amount:</strong> \${$order['amount']}</p>\n";
    echo "    <p><strong>Quantity:</strong> {$order['quantity']} × \${$order['denomination']}</p>\n";

    if ($order['discount'] > 0) {
        echo "    <p><strong>Discount:</strong> \${$order['discount']}</p>\n";
    }

    $statusClass = 'status-' . strtolower($order['status']);
    echo "    <p><strong>Status:</strong> ";
    echo "<span class='{$statusClass}'>{$order['status']}</span></p>\n";

    $date = date('F j, Y g:i A', strtotime($order['placed_at']));
    echo "    <p><strong>Placed On:</strong> {$date}</p>\n";
    echo "  </div>\n";

    // Display vouchers if available
    if ($order['status'] === 'delivered' && !empty($order['vouchers'])) {
        echo "  <div class='vouchers-section'>\n";
        echo "    <h3>📦 Delivered Vouchers</h3>\n";

        foreach ($order['vouchers'] as $index => $voucher) {
            $voucherNum = $index + 1;
            echo "    <div class='voucher-card'>\n";
            echo "      <h4>Voucher {$voucherNum}</h4>\n";

            // Card number
            if (!empty($voucher['card_number'])) {
                echo "      <div class='voucher-field'>\n";
                echo "        <label>Card Number:</label>\n";
                echo "        <div class='code-box'>\n";
                echo "          <code>{$voucher['card_number']}</code>\n";
                echo "          <button onclick='copyToClipboard(\"{$voucher['card_number']}\")'>";
                echo "Copy</button>\n";
                echo "        </div>\n";
                echo "      </div>\n";
            }

            // PIN code
            if (!empty($voucher['pin_code'])) {
                echo "      <div class='voucher-field'>\n";
                echo "        <label>PIN Code:</label>\n";
                echo "        <div class='code-box'>\n";
                echo "          <code>{$voucher['pin_code']}</code>\n";
                echo "          <button onclick='copyToClipboard(\"{$voucher['pin_code']}\")'>";
                echo "Copy</button>\n";
                echo "        </div>\n";
                echo "      </div>\n";
            }

            // Reference number
            if (!empty($voucher['voucher_reference_number'])) {
                echo "      <div class='voucher-field'>\n";
                echo "        <label>Reference Number:</label>\n";
                echo "        <code>{$voucher['voucher_reference_number']}</code>\n";
                echo "      </div>\n";
            }

            // Claim URL
            if (!empty($voucher['claim_url'])) {
                echo "      <div class='voucher-field'>\n";
                echo "        <a href='{$voucher['claim_url']}' ";
                echo "target='_blank' class='btn-redeem'>🎁 Redeem Voucher</a>\n";
                echo "      </div>\n";
            }

            // Expiration
            if (!empty($voucher['expires_at'])) {
                $expireDate = date('F j, Y', strtotime($voucher['expires_at']));
                echo "      <div class='expire-warning'>\n";
                echo "        Warning: Expires: {$expireDate}\n";
                echo "      </div>\n";
            }

            echo "    </div>\n";
        }

        echo "  </div>\n";

    } elseif ($order['status'] === 'processing') {
        echo "  <div class='status-message processing'>\n";
        echo "    <p>Order is being processed. Vouchers will be available soon.</p>\n";
        echo "    <p>Please check back in a few moments.</p>\n";
        echo "  </div>\n";

    } elseif ($order['status'] === 'pending') {
        echo "  <div class='status-message pending'>\n";
        echo "    <p>Order is pending. Processing will begin shortly.</p>\n";
        echo "  </div>\n";

    } elseif ($order['status'] === 'failed') {
        echo "  <div class='status-message failed'>\n";
        echo "    <p>Order processing failed. Please contact support.</p>\n";
        echo "  </div>\n";
    }

    echo "</div>\n";
}

// Monitor order until delivered
function waitForDelivery($api, $orderId, $maxWaitTime = 300) {
    $startTime = time();
    $checkInterval = 5; // Start with 5 seconds

    while ((time() - $startTime) < $maxWaitTime) {
        $order = getOrderDetails($api, $orderId);

        echo "Status: {$order['status']} ";
        echo "(checked at " . date('H:i:s') . ")\n";

        if ($order['status'] === 'delivered') {
            echo "Order delivered!\n";
            return $order;
        }

        if ($order['status'] === 'failed' || $order['status'] === 'cancelled') {
            echo "Order {$order['status']}.\n";
            return $order;
        }

        sleep($checkInterval);
        // Exponential backoff
        $checkInterval = min($checkInterval * 1.5, 30);
    }

    throw new Exception("Order did not complete within {$maxWaitTime} seconds");
}

// Secure voucher delivery via email
function sendVoucherEmail($order, $recipientEmail) {
    if ($order['status'] !== 'delivered' || empty($order['vouchers'])) {
        return false;
    }

    $subject = "Your Order #{$order['id']} - Vouchers Delivered";

    $message = "Dear Customer,\n\n";
    $message .= "Your order #{$order['id']} has been delivered.\n\n";
    $message .= "Order Details:\n";
    $message .= "Reference: {$order['reference_code']}\n";
    $message .= "Amount: \${$order['amount']}\n\n";
    $message .= "Your Vouchers:\n";
    $message .= str_repeat('-', 50) . "\n";

    foreach ($order['vouchers'] as $index => $voucher) {
        $voucherNum = $index + 1;
        $message .= "\nVoucher {$voucherNum}:\n";

        if (!empty($voucher['card_number'])) {
            $message .= "Card Number: {$voucher['card_number']}\n";
        }
        if (!empty($voucher['pin_code'])) {
            $message .= "PIN: {$voucher['pin_code']}\n";
        }
        if (!empty($voucher['claim_url'])) {
            $message .= "Redeem at: {$voucher['claim_url']}\n";
        }
        if (!empty($voucher['expires_at'])) {
            $expDate = date('F j, Y', strtotime($voucher['expires_at']));
            $message .= "Expires: {$expDate}\n";
        }

        $message .= str_repeat('-', 50) . "\n";
    }

    $message .= "\nThank you for your order!\n";

    // Send email (implement secure email sending)
    return mail($recipientEmail, $subject, $message);
}

// Example usage
$orderId = 12345;
displayOrderWithVouchers($api, $orderId);
?>

Error Responses

401 Unauthorized

{
  "error": "unauthorized",
  "message": "Invalid or expired access token"
}

404 Not Found

{
  "error": "not_found",
  "message": "No Matching Result Found!"
}

500 Internal Server Error

{
  "error": "internal_error",
  "message": "Failed to retrieve order"
}

Best Practices

Security

  1. Never Log Voucher Codes - Avoid logging sensitive voucher data
  2. Secure Display - Hide voucher codes by default, reveal on click
  3. Copy Protection - Implement copy-to-clipboard functionality
  4. Session Timeout - Auto-logout after viewing vouchers
  5. Audit Trail - Log voucher access for security monitoring

Performance

  1. Poll Efficiently - Use exponential backoff when checking status
  2. Cache Static Data - Cache delivered orders client-side
  3. Lazy Load Vouchers - Load vouchers only when needed
  4. Minimize API Calls - Batch status checks where possible

User Experience

  1. Status Indicators - Show clear order status with icons
  2. Progress Updates - Display processing progress if available
  3. Copy Functionality - Make voucher codes easy to copy
  4. Expiration Warnings - Highlight approaching expiration dates
  5. Redemption Links - Provide direct redemption URLs

Rate Limits

  • Standard Rate: 200 requests per minute
  • Burst Limit: 20 requests per 10 seconds
  • Per-Order Limit: 60 requests per order per hour

Rate limiting prevents:

  • Voucher harvesting attempts
  • Excessive status polling
  • Automated scraping

Monitoring Best Practices

Status Polling Strategy

<?php
// Recommended polling intervals
$pollingIntervals = [
    'initial' => 5,      // 5 seconds
    'standard' => 10,    // 10 seconds
    'slow' => 30,        // 30 seconds
    'maxDelay' => 60     // 1 minute max
];

// Exponential backoff implementation
$delay = $pollingIntervals['initial'];
$delay = min($delay * 1.5, $pollingIntervals['maxDelay']);
?>

Timeout Recommendations

  • Fast Products: 2-5 minutes
  • Standard Products: 5-10 minutes
  • Slow Products: 10-30 minutes

Next Steps