Create Order
Create a new eSIM order using your account balance.
Endpoint
POST /api/v1/business/esims/order
Authentication
This endpoint requires HMAC authentication. See Authentication for details.
Request Headers
Header | Type | Required | Description |
---|---|---|---|
RT-AccessCode | String | Yes | Your API access code |
RT-RequestID | String | Yes | Unique request ID (UUID v4) |
RT-Timestamp | String | Yes | Request timestamp in milliseconds |
RT-Signature | String | Yes | HMAC-SHA256 signature |
Content-Type | String | Yes | Must be "application/json" |
Request Body
Field | Type | Required | Description |
---|---|---|---|
packageCode | String | Yes | Package code from the packages endpoint |
packageName | String | Yes | Package display name |
price | Number | Yes | Package price (must match packages endpoint) |
quantity | Integer | No | Number of eSIMs to order (default: 1) |
duration | Integer | No | Duration in days (auto-detected from package name) |
flagUrl | String | No | Country flag URL |
Request Example
{
"packageCode": "merhaba-7days-1gb",
"packageName": "Turkey 1 GB 7 Days",
"price": 2.72,
"quantity": 1,
"duration": 7,
"flagUrl": "/img/flags/tr.png"
}
Response
Success Response (200 OK)
{
"success": true,
"message": "Order processed successfully",
"orderReference": "order_1692123456_ab7cd",
"esimId": 2503,
"packageName": "Turkey 1 GB 7 Days",
"newBalance": 47.28,
"qrCodeUrl": "https://qr.example.com/esim-qr-code.png",
"directAppleInstallUrl": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA:1$...",
"paymentMethod": "balance",
"status": "completed",
"amount": 2.72,
"profit": 0.2,
"final_price": 2.72,
"processing_time_ms": 3245,
"esims": [
{
"iccid": "8932042000010078801",
"qrCodeUrl": "https://qr.example.com/esim-qr-code.png",
"directAppleInstallUrl": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA:1$...",
"status": "New",
"isPending": false
}
]
}
Pending Response (200 OK)
When eSIM details are being processed:
{
"success": true,
"message": "Order created successfully, eSIM details will be available shortly",
"orderReference": "order_1692123456_ab7cd",
"esimId": 2503,
"packageName": "Turkey 1 GB 7 Days",
"newBalance": 47.28,
"qrCodeUrl": "",
"directAppleInstallUrl": "",
"paymentMethod": "balance",
"status": "pending_details",
"amount": 2.72,
"profit": 0.2,
"final_price": 2.72,
"processing_time_ms": 1523,
"note": "The order was placed successfully but eSIM details are being processed. Please check order status in a few minutes.",
"esims": [
{
"iccid": "PENDING_B25081719340002_1755459260253",
"qrCodeUrl": "",
"directAppleInstallUrl": "",
"status": "PENDING",
"isPending": true
}
]
}
Response Fields
Field | Type | Description |
---|---|---|
success | Boolean | Request success status |
message | String | Human-readable status message |
orderReference | String | Unique order reference for tracking |
esimId | Integer | Primary eSIM ID (for single eSIM orders) |
packageName | String | Ordered package name |
newBalance | Number | Your updated account balance |
qrCodeUrl | String | QR code for eSIM installation |
directAppleInstallUrl | String | Direct iPhone installation URL |
paymentMethod | String | Always "balance" for business orders |
status | String | Order status ("completed" or "pending_details") |
amount | Number | Total order amount |
profit | Number | Your profit amount from this order |
final_price | Number | Final price charged to your balance |
processing_time_ms | Integer | Order processing time in milliseconds |
esims | Array | Array of eSIM details |
note | String | Additional information (for pending orders) |
eSIM Object Fields
Field | Type | Description |
---|---|---|
iccid | String | eSIM ICCID number |
qrCodeUrl | String | QR code image URL |
directAppleInstallUrl | String | Direct Apple installation URL |
status | String | eSIM status ("New" or "PENDING") |
isPending | Boolean | Whether eSIM details are still being processed |
Order Status Checking
You can check the status of any order using the order reference:
GET /api/v1/business/esims/order?orderReference={orderReference}
Status Check Response
{
"success": true,
"order": {
"id": 2503,
"packageName": "Turkey 1 GB 7 Days",
"packageCode": "merhaba-7days-1gb",
"status": "completed",
"amount": 2.72,
"finalPrice": 2.72,
"orderDate": "2024-08-17T20:12:00Z",
"orderReference": "order_1692123456_ab7cd",
"paymentMethod": "balance",
"paymentStatus": "succeeded",
"esim": {
"iccid": "8932042000010078801",
"status": "New",
"qrCodeUrl": "https://qr.example.com/esim-qr-code.png",
"directAppleInstallUrl": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA:1$...",
"unlimited": false,
"totalVolume": 1073741824,
"totalDuration": 7,
"expiredTime": "2025-02-13T20:12:00Z"
}
}
}
Examples
Basic Order Creation
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
async function createOrder(packageDetails) {
const accessCode = 'esf_your_access_code';
const secretKey = 'sk_your_secret_key';
// Order data
const orderData = {
packageCode: packageDetails.package_code,
packageName: packageDetails.name,
price: packageDetails.cost,
quantity: 1,
duration: packageDetails.validity_days,
flagUrl: packageDetails.locationNetworkList?.[0]?.locationLogo || ''
};
// Generate HMAC headers
const timestamp = Date.now().toString();
const requestId = uuidv4();
const requestBody = JSON.stringify(orderData);
const signData = timestamp + requestId + accessCode + requestBody;
const signature = crypto.createHmac('sha256', secretKey)
.update(signData)
.digest('hex')
.toUpperCase();
const response = await fetch('https://esimfly.net/api/v1/business/esims/order', {
method: 'POST',
headers: {
'RT-AccessCode': accessCode,
'RT-RequestID': requestId,
'RT-Timestamp': timestamp,
'RT-Signature': signature,
'Content-Type': 'application/json'
},
body: requestBody
});
const result = await response.json();
if (result.success) {
console.log(`Order created: ${result.orderReference}`);
console.log(`New balance: $${result.newBalance}`);
console.log(`Profit earned: $${result.profit}`);
// Save eSIM details for customer
result.esims.forEach((esim, index) => {
console.log(`eSIM ${index + 1}: ${esim.iccid}`);
console.log(`QR Code: ${esim.qrCodeUrl}`);
});
}
return result;
}
Multiple eSIM Order
const orderData = {
packageCode: "europe-5gb-30days",
packageName: "Europe 5GB 30 Days",
price: 15.99,
quantity: 5, // Order 5 eSIMs
flagUrl: "/img/flags/eu.png"
};
const result = await createOrder(orderData);
if (result.success) {
console.log(`Created ${result.esims.length} eSIMs`);
console.log(`Total cost: $${result.final_price}`);
console.log(`Total profit: $${result.profit}`);
}
Check Order Status
async function checkOrderStatus(orderReference) {
const response = await fetch(
`https://esimfly.net/api/v1/business/esims/order?orderReference=${orderReference}`,
{
headers: generateHMACHeaders() // Your HMAC function
}
);
const data = await response.json();
if (data.success) {
console.log(`Order Status: ${data.order.status}`);
console.log(`Payment Status: ${data.order.paymentStatus}`);
console.log(`eSIM Status: ${data.order.esim.status}`);
}
return data;
}
Python Example
import hashlib
import hmac
import json
import time
import uuid
import requests
def create_esim_order(package_code, package_name, price, quantity=1):
access_code = 'esf_your_access_code'
secret_key = 'sk_your_secret_key'
# Order data
order_data = {
'packageCode': package_code,
'packageName': package_name,
'price': price,
'quantity': quantity
}
# Generate HMAC headers
timestamp = str(int(time.time() * 1000))
request_id = str(uuid.uuid4())
request_body = json.dumps(order_data)
sign_data = timestamp + request_id + access_code + request_body
signature = hmac.new(
secret_key.encode('utf-8'),
sign_data.encode('utf-8'),
hashlib.sha256
).hexdigest().upper()
headers = {
'RT-AccessCode': access_code,
'RT-RequestID': request_id,
'RT-Timestamp': timestamp,
'RT-Signature': signature,
'Content-Type': 'application/json'
}
response = requests.post(
'https://esimfly.net/api/v1/business/esims/order',
headers=headers,
json=order_data
)
data = response.json()
if data['success']:
print(f"Order created: {data['orderReference']}")
print(f"New balance: ${data['newBalance']}")
print(f"Profit: ${data['profit']}")
for i, esim in enumerate(data['esims']):
print(f"eSIM {i+1}: {esim['iccid']}")
return data
# Example usage
result = create_esim_order(
package_code='merhaba-7days-1gb',
package_name='Turkey 1 GB 7 Days',
price=2.72,
quantity=1
)
Error Responses
400 Bad Request
Missing required fields:
{
"success": false,
"message": "Missing required fields",
"code": "MISSING_FIELDS"
}
Invalid package:
{
"success": false,
"message": "Invalid package selected",
"code": "INVALID_PACKAGE"
}
Price mismatch (security validation):
{
"success": false,
"message": "Invalid price submitted",
"code": "PRICE_MISMATCH"
}
Insufficient balance:
{
"success": false,
"message": "Insufficient balance",
"code": "INSUFFICIENT_BALANCE",
"currentBalance": 25.50,
"requiredBalance": 27.20,
"needToLoad": 1.70
}
401 Unauthorized
Missing authentication:
{
"success": false,
"error": "Authentication required",
"message": "Please provide either Bearer token or complete HMAC signature authentication"
}
Invalid HMAC signature:
{
"success": false,
"error": "Invalid HMAC signature",
"code": "INVALID_SIGNATURE"
}
403 Forbidden
Not a business account:
{
"success": false,
"error": "Invalid user or not a business account",
"code": "INVALID_USER"
}
500 Internal Server Error
Order processing error:
{
"success": false,
"message": "Failed to process order",
"code": "ORDER_PROCESSING_ERROR"
}
Order Flow
- Get Packages: Use
/packages
endpoint to get available packages - Select Package: Choose a package and extract the required fields
- Create Order: Submit order with exact package details
- Balance Deduction: Your balance is automatically deducted
- eSIM Provisioning: eSIM is provisioned from the provider
- Response: Receive eSIM details or pending status
- Status Check: Monitor order status if initially pending
Security Features
Price Validation
- Server-side price validation prevents price manipulation
- Submitted price must match the current package price
- Prices are validated against live package data
Balance Safety
- Balance is checked before processing
- Atomic transaction ensures balance consistency
- No partial deductions on failed orders
Request Deduplication
- Each request requires a unique UUID v4 request ID
- Duplicate request IDs are rejected to prevent accidental reorders
- Request IDs are stored for 24 hours
Best Practices
1. Always Use Latest Package Data
// Good: Get fresh package data
const packages = await getPackages({ search: 'Turkey' });
const selectedPackage = packages.data.packages[0];
const order = await createOrder({
packageCode: selectedPackage.package_code,
packageName: selectedPackage.name,
price: selectedPackage.cost // Use current price
});
2. Handle Pending Orders
const result = await createOrder(orderData);
if (result.status === 'pending_details') {
console.log('Order created, waiting for eSIM details...');
// Check status after a delay
setTimeout(async () => {
const status = await checkOrderStatus(result.orderReference);
if (status.order.status === 'completed') {
console.log('eSIM details now available!');
}
}, 60000); // Check after 1 minute
}
3. Monitor Your Balance
const result = await createOrder(orderData);
if (result.success) {
console.log(`Order total: $${result.final_price}`);
console.log(`Profit earned: $${result.profit}`);
console.log(`Remaining balance: $${result.newBalance}`);
// Alert if balance is low
if (result.newBalance < 10) {
console.warn('Low balance! Consider topping up.');
}
}
4. Store eSIM Details Securely
const result = await createOrder(orderData);
if (result.success) {
// Store eSIM details in your database
for (const esim of result.esims) {
await storeEsimForCustomer({
customerEmail: customerEmail,
packageName: result.packageName,
iccid: esim.iccid,
qrCodeUrl: esim.qrCodeUrl,
installUrl: esim.directAppleInstallUrl,
orderReference: result.orderReference
});
}
}
Package Code Requirements
Format Examples
- Standard:
merhaba-7days-1gb
- ESIMGo:
esim_UL_1D_TR_V2
- ESIMAccess:
PHAJHEAYP
Important Notes
- Use the exact
package_code
from the packages endpoint - Do not modify or prefix package codes
- Package codes are provider-specific but abstracted from you
Quantity Limits
- Minimum: 1 eSIM per order
- Maximum: 10 eSIMs per order
- Multiple Orders: For larger quantities, create multiple orders
- Same ICCID: Each eSIM in an order has a unique ICCID
Rate Limiting
This endpoint is subject to:
- 1000 requests per hour per API key
- Rate limit headers included in responses
Troubleshooting
Common Issues
-
Price Mismatch Error
- Ensure you're using the latest package price
- Package prices may change; always fetch fresh data
-
Insufficient Balance
- Check your balance with
/balance
endpoint - Top up your account before placing orders
- Check your balance with
-
Invalid Package Code
- Verify package code exists in packages endpoint
- Package availability may change
-
Pending eSIM Details
- Normal for some providers during high load
- Check order status after 1-2 minutes
- Contact support if pending for > 5 minutes
Error Handling Example
try {
const result = await createOrder(orderData);
if (!result.success) {
switch (result.code) {
case 'INSUFFICIENT_BALANCE':
console.error(`Need to top up: $${result.needToLoad}`);
break;
case 'PRICE_MISMATCH':
console.error('Price has changed, refresh package data');
break;
case 'INVALID_PACKAGE':
console.error('Package no longer available');
break;
default:
console.error('Order failed:', result.message);
}
}
} catch (error) {
console.error('Network error:', error.message);
}
Support
For technical support or questions about the order API:
- Email: support@esimfly.net
- Response Time: 24 hours
- Documentation: https://docs.esimfly.net