Create Order API
Submit new voucher orders for digital products with automatic wallet deduction and voucher link generation
Create Order API
Submit a new voucher order for digital products including gift cards, mobile top-ups, and digital services. Orders are processed with immediate wallet deduction and delivered based on quantity and availability.
Endpoint
POST /api/v1/ordersAuthentication: Bearer token required
Request Headers
Authorization: Bearer <access_token>
Content-Type: application/jsonRequest Body
Required Fields
{
"product_id": 6,
"denomination": 25.00,
"quantity": 5
}Complete Request Schema
{
"product_id": 6,
"denomination": 25.00,
"quantity": 5,
"wallet_id": 1234,
"ref": "CLIENT_REF_123456",
"email": "customer@example.com"
}Field Descriptions
| Field | Type | Required | Description |
|---|---|---|---|
product_id | number | Yes | Product ID from the catalog (must be > 0) |
denomination | number | Yes | Amount per voucher (must be > 0.00) |
quantity | number | Yes | Number of vouchers to create (min: 1) |
wallet_id | number | No | Specific wallet for payment (auto-selected if omitted) |
ref | string | No | Client reference for tracking (auto-generated UUID if omitted) |
email | string | No | Customer email for voucher delivery (must be valid email format) |
Validation Rules
- product_id: Must reference an active product in the catalog
- denomination: Must match available denominations for the product
- quantity: Maximum varies by product and client limits (bulk limit)
- wallet_id: Must belong to authenticated client and have sufficient balance
- ref: Must be unique if provided (no duplicate reference codes)
- email: Must be valid email format when provided
Response
Success Response
Status Code: 200 OK
{
"id": 1234,
"ref": "1757321938LIGPWWSL7JKOKVPADF422WSXTA",
"transaction_id": 5678,
"amount": 127.50,
"product_id": 6,
"denomination": 25.00,
"quantity": 5,
"discount": 2.50,
"vouchers": [],
"status": "PENDING",
"placed_at": "2024-01-15T10:30:00Z"
}For orders that are immediately delivered, the vouchers array will contain voucher details:
{
"id": 1234,
"ref": "1757321938LIGPWWSL7JKOKVPADF422WSXTA",
"transaction_id": 5678,
"amount": 127.50,
"product_id": 6,
"denomination": 25.00,
"quantity": 2,
"discount": 2.50,
"vouchers": [
{
"card_number": "1234-5678-9012-3456",
"pin_code": "ABC123",
"claim_url": "{{host}}/vouchers/claim/abc123...",
"expires_at": "2025-12-31T23:59:59Z",
"voucher_reference_number": "VOUCHER_REF_001"
}
],
"status": "DELIVERED",
"placed_at": "2024-01-15T10:30:00Z"
}Response Fields
| Field | Type | Description |
|---|---|---|
id | number | Unique order identifier |
ref | string | Reference code for the order |
transaction_id | number | Wallet transaction ID |
amount | number | Total order amount (after discounts and fees) |
product_id | number | Product ID from the request |
denomination | number | Individual voucher amount |
quantity | number | Number of vouchers in the order |
discount | number | Total discount applied |
vouchers | array | Array of voucher codes (empty for PENDING orders) |
status | string | Order status (see Order Statuses) |
placed_at | string | Order creation timestamp in ISO 8601 format |
Voucher Object Structure
{
"card_number": "1234-5678-9012-3456",
"pin_code": "1234",
"code": "GIFT-CODE-123",
"pin": "5678",
"claim_url": "{{host}}/vouchers/claim/token_hash",
"expires_at": "2025-12-31T23:59:59Z",
"voucher_reference_number": "VOUCHER_REF_123"
}Voucher Fields:
| Field | Type | Description |
|---|---|---|
card_number | string | Gift card or voucher number |
pin_code | string | PIN code for redemption |
code | string | Alternative code field |
pin | string | Alternative PIN field |
claim_url | string | Web URL to claim the voucher |
expires_at | string | Expiration date in ISO 8601 format |
voucher_reference_number | string | Reference number for the voucher |
Note: Not all fields are present for every voucher. The fields returned depend on the product type.
Error Responses
400 Bad Request - Invalid Request
{
"error": "BadRequest",
"message": "Invalid request body format"
}400 Bad Request - Validation Errors
{
"error": "BadRequest",
"message": "Invalid Quantity: min"
}400 Bad Request - Insufficient Funds
{
"error": "BadRequest",
"message": "Insufficient funds in your wallet"
}400 Bad Request - Quantity Limit Exceeded
{
"error": "BadRequest",
"message": "Invalid quantity, allowed max quantity: 1000"
}400 Bad Request - Denomination Not Available
{
"error": "BadRequest",
"message": "Denomination not available for this product"
}400 Bad Request - Duplicate Reference
{
"error": "BadRequest",
"message": "Duplicate reference code"
}401 Unauthorized
{
"error": "UnauthorizedAccess",
"message": "User is not authorised to perform this action"
}404 Not Found - Product Not Available
{
"error": "NotFound",
"message": "Product not found"
}404 Not Found - Wallet Not Found
{
"error": "NotFound",
"message": "Wallet not found"
}500 Internal Server Error
{
"error": "InternalServerError",
"message": "Failed to create order"
}Order Statuses
Orders progress through different statuses during processing:
| Status | Description | Wallet Deduction | Vouchers Available |
|---|---|---|---|
PENDING | Order created, processing in progress | Yes (Deducted) | No (Not yet) |
DELIVERED | Order completed successfully | Yes (Deducted) | Yes (Available) |
PARTIALLY_DELIVERED | Some vouchers delivered | Yes (Deducted) | Yes (Some available) |
FAILED | Order processing failed | No (Refunded) | No (None) |
CANCELLED | Order was cancelled | No (Refunded) | No (None) |
Status Flow
Order Creation → PENDING → DELIVERED
↓
FAILED (if processing fails)Important: Wallet deduction happens immediately upon order creation. The wallet balance is deducted as soon as the order is created successfully, even while the order is still in PENDING status.
Wallet Deduction Process
Automatic Wallet Selection
If wallet_id is not provided, the system automatically selects the most appropriate wallet:
- Checks for wallets matching the product's currency
- Selects wallet with sufficient balance
- Applies forex conversion if necessary
Immediate Deduction
The wallet balance is deducted immediately when the order is created:
- Transaction is created with type
ORDER - Balance is reduced by the total order amount
- Transaction is linked to the order for audit trail
Multi-Currency Support
The system handles currency conversion automatically:
- If wallet currency differs from product currency, forex rates are applied
- Conversion charges may be added based on client configuration
- All conversions are logged in the transaction history
Voucher Link Types
Claim URLs
For products that provide web-based claim links:
{
"claim_url": "{{host}}/vouchers/claim/token_hash",
"expires_at": "2025-12-31T23:59:59Z",
"voucher_reference_number": "WEB_VOUCHER_12345"
}Direct Voucher Codes
For products that provide voucher codes directly:
{
"card_number": "1234-5678-9012-3456",
"pin_code": "1234",
"expires_at": "2025-12-31T23:59:59Z",
"voucher_reference_number": "AMZN_GIFT_12345"
}Alternative Code Format
Some vouchers provide codes in alternative formats:
{
"code": "GIFT-ABC-123-XYZ",
"pin": "9876",
"expires_at": "2025-12-31T23:59:59Z",
"voucher_reference_number": "ALT_CODE_12345"
}Order Processing
Orders are processed automatically after creation:
- Small Orders (quantity ≤ 10): Processed immediately and may include vouchers in the response
- Large Orders (quantity > 10): Processed asynchronously in the background with PENDING status initially
Testing Realtime Orders
For testing realtime order processing:
- Product IDs 7 and 8 are specifically configured for testing realtime orders
- These products will always process orders in realtime regardless of quantity
- Other products may or may not support realtime processing and might have stocked inventory
Test Request Examples
# Test realtime order with Product ID 7
curl -X POST "{{host}}/api/v1/orders" \
-H "Authorization: Bearer your_test_token" \
-H "Content-Type: application/json" \
-d '{
"product_id": 7,
"denomination": 10.00,
"quantity": 5
}'
# Test realtime order with Product ID 8 (large quantity)
# This will still process in realtime despite quantity > 10
curl -X POST "{{host}}/api/v1/orders" \
-H "Authorization: Bearer your_test_token" \
-H "Content-Type: application/json" \
-d '{
"product_id": 8,
"denomination": 25.00,
"quantity": 20,
"ref": "TEST_REALTIME_BULK"
}'
# Test async order with other product (quantity > 10)
curl -X POST "{{host}}/api/v1/orders" \
-H "Authorization: Bearer your_test_token" \
-H "Content-Type: application/json" \
-d '{
"product_id": 6,
"denomination": 50.00,
"quantity": 15,
"ref": "TEST_ASYNC_ORDER"
}'<?php
// Test realtime order with Product ID 7
function testRealtimeOrder($accessToken) {
$url = '{{host}}/api/v1/orders';
// Test with Product 7 - always realtime
$testData1 = [
'product_id' => 7,
'denomination' => 10.00,
'quantity' => 5
];
$options = [
'http' => [
'header' => [
"Content-Type: application/json",
"Authorization: Bearer $accessToken"
],
'method' => 'POST',
'content' => json_encode($testData1)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$response = json_decode($result, true);
echo "Test 1 - Product 7 (quantity 5):\n";
echo "Status: " . $response['status'] . "\n";
echo "Vouchers Available: " . (empty($response['vouchers']) ? 'No' : 'Yes') . "\n\n";
// Test with Product 8 - large quantity, still realtime
$testData2 = [
'product_id' => 8,
'denomination' => 25.00,
'quantity' => 20,
'ref' => 'TEST_REALTIME_BULK'
];
$options['http']['content'] = json_encode($testData2);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$response = json_decode($result, true);
echo "Test 2 - Product 8 (quantity 20, realtime despite > 10):\n";
echo "Status: " . $response['status'] . "\n";
echo "Vouchers Available: " . (empty($response['vouchers']) ? 'No' : 'Yes') . "\n\n";
// Test with regular product - async when quantity > 10
$testData3 = [
'product_id' => 6,
'denomination' => 50.00,
'quantity' => 15,
'ref' => 'TEST_ASYNC_ORDER'
];
$options['http']['content'] = json_encode($testData3);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$response = json_decode($result, true);
echo "Test 3 - Product 6 (quantity 15, should be async):\n";
echo "Status: " . $response['status'] . "\n";
echo "Vouchers Available: " . (empty($response['vouchers']) ? 'No' : 'Yes') . "\n";
echo "Expected: PENDING status with no vouchers initially\n";
return $response;
}
// Usage
$accessToken = 'your_test_token';
testRealtimeOrder($accessToken);
?>Asynchronous Processing
Orders will be marked for asynchronous processing and delivered asynchronously when:
- The order quantity exceeds 10 (except for products 7 and 8 which are always realtime)
- The product does not support realtime processing
- Inventory needs to be fetched from stock
Order Lifecycle
- Order Creation: Order is created and wallet balance is deducted immediately
- Processing: Vouchers are generated and validated
- Delivery: Order status is updated and notifications sent (if email provided)
Tip: Use the Get Order Details API to check processing status and retrieve vouchers when ready.
Examples
Simple Order Creation
# Create a simple voucher order
curl -X POST "{{host}}/api/v1/orders" \
-H "Authorization: Bearer your_access_token" \
-H "Content-Type: application/json" \
-d '{
"product_id": 6,
"denomination": 25.00,
"quantity": 2
}'<?php
function createVoucherOrder($accessToken, $productId, $denomination, $quantity) {
$url = '{{host}}/api/v1/orders';
$data = [
'product_id' => $productId,
'denomination' => $denomination,
'quantity' => $quantity
];
$options = [
'http' => [
'header' => [
"Content-Type: application/json",
"Authorization: Bearer $accessToken"
],
'method' => 'POST',
'content' => json_encode($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result, true);
}
// Usage
$response = createVoucherOrder(
'your_access_token',
6, // Amazon Gift Card
25.00, // $25 denomination
2 // 2 vouchers
);
if (isset($response['id'])) {
echo "Order ID: " . $response['id'] . "\n";
echo "Status: " . $response['status'] . "\n";
echo "Reference: " . $response['ref'] . "\n";
}
?>Advanced Order with Custom Parameters
{
"product_id": 15,
"denomination": 50.00,
"quantity": 10,
"wallet_id": 1234,
"ref": "PROMO_BATCH_2024_001",
"email": "customer@example.com"
}Bulk Order Creation
# Create multiple orders for different products
curl -X POST "{{host}}/api/v1/orders" \
-H "Authorization: Bearer your_access_token" \
-H "Content-Type: application/json" \
-d '{
"product_id": 6,
"denomination": 25.00,
"quantity": 100,
"ref": "BULK_AMAZON_CARDS_2024"
}'Error Handling Example
async function createOrderWithErrorHandling(orderData) {
try {
const response = await fetch('/api/v1/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getAccessToken()}`
},
body: JSON.stringify(orderData)
});
const result = await response.json();
if (!response.ok) {
// Handle different error types
switch (response.status) {
case 400:
console.error('Bad Request:', result.message);
break;
case 401:
console.error('Unauthorized:', result.message);
break;
case 404:
console.error('Not Found:', result.message);
break;
case 500:
console.error('Internal Server Error:', result.message);
break;
default:
console.error('Order creation failed:', result.message);
}
throw new Error(result.message);
}
return result;
} catch (error) {
console.error('Network or parsing error:', error.message);
throw error;
}
}Best Practices
Pre-Order Validation
- Check Product Availability - Use the Products API to verify product status and available denominations
- Calculate Charges - Use the Charges API to show exact pricing including fees and discounts
- Validate Wallet Balance - Ensure sufficient funds before order creation
- Verify Denominations - Confirm the requested denomination is supported for the product
Order Creation Best Practices
- Use Unique Reference Numbers - Include client reference codes to prevent duplicate processing
- Handle Async Processing - Implement polling or webhooks for order status updates
- Store Order IDs - Save the returned order ID for tracking, support, and reconciliation
- Batch Large Orders - For high quantities, consider splitting into smaller batches
Error Handling Strategies
- Implement Exponential Backoff - For 5xx server errors and rate limits
- Don't Retry Validation Errors - 4xx errors typically require request modification
- Log Order Attempts - Maintain audit trails for troubleshooting and reconciliation
- Handle Partial Failures - Account for
PARTIALLY_DELIVEREDstatus in bulk orders
Monitoring and Observability
- Track Success Rates - Monitor order creation and delivery success metrics
- Set Up Alerts - Alert on unusual failure rates or processing delays
- Monitor Wallet Balances - Ensure adequate funding for automated systems
- Track Voucher Usage - Monitor claim rates and expiration patterns
Security Considerations
API Security
- Always use HTTPS for all API communications
- Secure Access Tokens - Store bearer tokens securely, rotate regularly
- Validate Inputs - Sanitize and validate all request data client-side
- Implement Request Signing - Use HMAC signatures for additional security
Sensitive Data Handling
- Never log voucher codes or claim URLs in plain text
- Encrypt storage of order references and customer data
- Implement audit trails for all order creation and modification activities
- Use secure channels for voucher delivery (HTTPS, encrypted email)
Rate Limits
The Create Order API implements multiple rate limiting tiers:
| Limit Type | Restriction | Reset Period |
|---|---|---|
| Per Minute | 60 requests | 1 minute |
| Burst Limit | 10 requests | 10 seconds |
| Daily Orders | 5,000 orders | 24 hours |
| Concurrent | 3 parallel requests | Real-time |
Rate Limit Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640995200
Retry-After: 30Integration Testing
Test Order Creation
# Test with minimal required fields
curl -X POST "{{host}}/api/v1/orders" \
-H "Authorization: Bearer test_token_123" \
-H "Content-Type: application/json" \
-d '{
"product_id": 6,
"denomination": 5.00,
"quantity": 1
}' | jq '.'Validate Order Processing
- Create Test Order - Use small denomination and quantity
- Monitor Status - Check order status progression
- Verify Wallet Deduction - Confirm correct amount deducted
- Test Voucher Delivery - Ensure vouchers are accessible
Webhooks (Available)
Monitor order status changes with webhook notifications:
Event Types
order.created- Order successfully created withPENDINGstatusorder.processing- Order processing startedorder.delivered- Order completed successfully with vouchers availableorder.partially_delivered- Some vouchers delivered, others still processingorder.failed- Order processing failed, wallet refundedorder.cancelled- Order cancelled by client or system
Webhook Payload Example
{
"event": "order.delivered",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"order_id": 12345,
"ref": "1757321938LIGPWWSL7JKOKVPADF422WSXTA",
"status": "DELIVERED",
"vouchers_ready": 5,
"total_vouchers": 5
}
}Performance Considerations
Optimal Request Patterns
- Batch Similar Orders - Group orders by product when possible
- Stagger Large Volumes - Distribute bulk orders over time
- Use Async Processing - Don't block on immediate voucher availability
- Implement Caching - Cache product information to reduce API calls
Technical Details
Order Processing
- Transaction Safety: All order operations are atomic - if any part fails, the entire order is rolled back
- Immediate Deduction: Wallet balance is deducted when the order is created
- Status Updates: Orders progress through statuses based on processing completion
- Performance: Large orders are processed efficiently in the background
Next Steps
Immediate Actions
- Set Up Authentication - Get API credentials
- Test Product Catalog - Browse available products
- Check Wallet Balances - Manage wallet funds
Advanced Integration
- Implement Status Polling - Get order details
- Set Up Webhooks - Monitor order events in real-time
- Build Reconciliation - List and filter orders
- Handle Refunds - Process cancelled or failed orders
Production Readiness
- Load Testing - Test with expected order volumes
- Monitor Integration - Set up logging and alerting
- Backup Systems - Implement failover for critical flows
- Documentation - Document your integration for team reference