Skip to main content

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

HeaderTypeRequiredDescription
RT-AccessCodeStringYesYour API access code
RT-RequestIDStringYesUnique request ID (UUID v4)
RT-TimestampStringYesRequest timestamp in milliseconds
RT-SignatureStringYesHMAC-SHA256 signature
Content-TypeStringYesMust be "application/json"

Request Body

FieldTypeRequiredDescription
packageCodeStringYesPackage code from the packages endpoint
packageNameStringYesPackage display name
priceNumberYesPackage price (must match packages endpoint)
quantityIntegerNoNumber of eSIMs to order (default: 1)
durationIntegerNoDuration in days (auto-detected from package name)
flagUrlStringNoCountry 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

FieldTypeDescription
successBooleanRequest success status
messageStringHuman-readable status message
orderReferenceStringUnique order reference for tracking
esimIdIntegerPrimary eSIM ID (for single eSIM orders)
packageNameStringOrdered package name
newBalanceNumberYour updated account balance
qrCodeUrlStringQR code for eSIM installation
directAppleInstallUrlStringDirect iPhone installation URL
paymentMethodStringAlways "balance" for business orders
statusStringOrder status ("completed" or "pending_details")
amountNumberTotal order amount
profitNumberYour profit amount from this order
final_priceNumberFinal price charged to your balance
processing_time_msIntegerOrder processing time in milliseconds
esimsArrayArray of eSIM details
noteStringAdditional information (for pending orders)

eSIM Object Fields

FieldTypeDescription
iccidStringeSIM ICCID number
qrCodeUrlStringQR code image URL
directAppleInstallUrlStringDirect Apple installation URL
statusStringeSIM status ("New" or "PENDING")
isPendingBooleanWhether 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

  1. Get Packages: Use /packages endpoint to get available packages
  2. Select Package: Choose a package and extract the required fields
  3. Create Order: Submit order with exact package details
  4. Balance Deduction: Your balance is automatically deducted
  5. eSIM Provisioning: eSIM is provisioned from the provider
  6. Response: Receive eSIM details or pending status
  7. 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

  1. Price Mismatch Error

    • Ensure you're using the latest package price
    • Package prices may change; always fetch fresh data
  2. Insufficient Balance

    • Check your balance with /balance endpoint
    • Top up your account before placing orders
  3. Invalid Package Code

    • Verify package code exists in packages endpoint
    • Package availability may change
  4. 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: