MớiREST API kèm tệp OpenAPI 3.1
API eSIM cho đại lý du lịch, OTA và đơn vị bán lại
Bán eSIM du lịch qua một REST API. Liệt kê gói dữ liệu theo quốc gia với giá theo tiền tệ của đại lý, đặt eSIM cho du khách, gửi mã QR cho du khách, theo dõi dung lượng đã dùng và nạp thêm dữ liệu. Một Base URL phục vụ cả sandbox và Live. Hãy bắt đầu bằng khóa sandbox miễn phí; khóa Live hoạt động sau khi đại lý của bạn được duyệt.
Tài liệu được viết bằng tiếng Anh.
- Base URL
https://api.fx-port.com/api/v1- Xác thực
Authorization: Bearer fxp_test_...- Tiền tố khóa
fxp_test_ / fxp_live_- Endpoint
- 12
- Quốc gia có gói
- 190+
- Ngôn ngữ mã mẫu
- 9
API eSIM, từng lệnh gọi một
Theo dõi từng bước một lần bán eSIM khi mỗi yêu cầu được tạo, gửi và nhận phản hồi. Các phiên gồm bán eSIM, giữ du khách luôn kết nối, kiểm tra thiết bị và đơn đặt, cùng những lỗi đáng xử lý. Yêu cầu và phản hồi là ví dụ lấy từ tài liệu, và trang này không bao giờ gọi API thật.
3 yêu cầu: Liệt kê các gói, Đặt eSIM, Đọc dữ liệu cài đặt.
Phiên minh họa: phần body là ví dụ lấy từ tài liệu, ngày được dời về sau để luôn nằm sau hôm nay, và thời gian chỉ mang tính minh họa. Trang này không gửi yêu cầu nào.
Tìm gói, đặt gói, đọc dữ liệu cài đặt
Bắt đầu với các gói của một quốc gia, đặt một gói cho du khách, rồi đọc dữ liệu cài đặt của đơn. Sandbox tạo một eSIM thử với mã kích hoạt giả và không trừ khoản nào, còn console hiển thị bản rút gọn của phản hồi danh mục gói.
Liệt kê các gói
Lệnh gọi danh mục nhận
countryvàtyperồi trả về các gói phù hợp, với giá theo tiền tệ của đại lý. Hãy giữpackage_idcủa gói du khách chọn.Yêu cầu GET /esims/packages curl 'https://api.fx-port.com/api/v1/esims/packages?country=france&type=local' \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 180 ms · 3.6 KB 200 OK Content-Type: application/json Cache-Control: private, no-store X-Environment: sandbox ratelimit-limit: 6000 ratelimit-policy: 6000;w=60 { "environment": "sandbox", "success": true, "endpoint": "/packages", "data": [ { "id": "france-in-7days-1gb", "package_id": "france-in-7days-1gb", "type": "sim", "price": 402.5, "base_price": 402.5, "amount": 1024, "day": 7, "is_unlimited": false, "title": "1 GB - 7 days", "is_fair_usage_policy": false, "fair_usage_policy": null, "data": "1 GB", "voice": null, "text": null, "country_name": "France", "country_code": "FR", "country_slug": "france", // ... "operator_name": "KPN France Data only", "operator_id": 1704, // ... "operator_type": "local", "operator_is_prepaid": false, "operator_esim_type": "Prepaid", "operator_warning": null, "operator_apn_type": "automatic", "operator_is_roaming": true, // ... "operator_plan_type": "data", "operator_activation_policy": "first-usage", "operator_is_kyc_verify": false, "operator_rechargeability": true, // ... // ... 1 more // ... "is_regional": false, // ... 10 more }, // ... ], "meta": { "total_packages": 12, "filters_applied": { // ... 2 more }, "locale": "en", "agency_currency": "DZD", "currency": "DZD", "supplier_currency": "USD", "exchange_rate": 250, "commission_percentage": "12 %", "commission_rate": 12 } }Ví dụ đã rút gọn để hiển thị
- PASS Mã trạng thái là 200
- PASS $.success bằng true
- PASS $.data[0].package_id tồn tại
- PASS $.data[0].balance_debit_amount tồn tại
Đặt eSIM
Tạo đơn nhận
package_idcùng địa chỉ email và số điện thoại của du khách. Hãy giữbooking_idvàdata.iccidtrong phản hồi. Ở sandbox,balanceDebited,transactionCreatedvàpayoutCreatedđều làfalse.Yêu cầu POST /esims/orders curl https://api.fx-port.com/api/v1/esims/orders \ -H "Authorization: Bearer fxp_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "package_id": "france-in-7days-1gb", "first_name": "John", "last_name": "Smith", "email": "[email protected]", "phone": "+15555550123", "description": "Order for John Smith" }'Phản hồi 200 OK · 900 ms · 1.5 KB 200 OK Content-Type: application/json Cache-Control: private, no-store X-Environment: sandbox ratelimit-limit: 1200 ratelimit-policy: 1200;w=60 x-fx-limit-class: booking { "environment": "sandbox", "success": true, "data": { "order": { "code": "20261101-106852", "order_id": "20261101-106852", "package_id": "france-in-7days-1gb", "type": "sim", "description": "Order for John Smith", "esim_type": "local", "created_at": "2026-11-09 15:23:22", "package": "KPN France Data only-1 GB - 7 days", "data": "1 GB", "validity": 7, "price": 468.84, "currency": "DZD", "total_price": 468.84, "retail_price": 468.84, "agency_currency": "DZD", "supplier_currency": "USD", "exchange_rate": 250, "voice": null, "text": null, "coverage": "" }, "sim": { "iccid": "8900000540463077957", "created_at": "2026-11-09 15:23:22", "lpa": "lpa.airalo.com", "imsis": null, "qrcode": "LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741", // ... "direct_apple_installation_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741", "apn_type": "automatic", "apn_value": "N/A", "apn": { // ... 2 more }, "is_roaming": true, "confirmation_code": null, "msisdn": null, "sharing": { "access_code": 8803, "link": "https://esims.cloud/v8hy7-usgkq6wg" } }, "iccid": "8900000540463077957" }, "booking_id": "FX-1793546602916", "message": "eSIM order placed successfully", "balanceDebited": false, "balance_debited": false, "transactionCreated": false, "transaction_created": false, "payoutCreated": false, "payout_created": false }Ví dụ đã rút gọn để hiển thị
- PASS Mã trạng thái là 200
- PASS $.environment bằng sandbox
- PASS $.balance_debited bằng false
- PASS $.data.iccid tồn tại
Đọc dữ liệu cài đặt
Lệnh gọi dữ liệu cài đặt nhận
booking_idvà trả về mã QR, dữ liệu kích hoạt, liên kết cài đặt và các bước cài đặt của đơn. Chỉ hiển thị cho du khách sở hữu eSIM.Yêu cầu GET /esims/bookings/{booking_id}/setup-instructions curl https://api.fx-port.com/api/v1/esims/bookings/FX-1793546602916/setup-instructions \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 210 ms · 1.8 KB 200 OK Content-Type: application/json Cache-Control: private, no-store X-Environment: sandbox ratelimit-limit: 6000 ratelimit-policy: 6000;w=60 { "environment": "sandbox", "success": true, "data": { "code": "20261101-106852", "order_id": "20261101-106852", "currency": "DZD", "package_id": "france-in-7days-1gb", "quantity": 1, "type": "sim", "description": "Order for John Smith", "esim_type": "local", "validity": 7, "package": "KPN France Data only-1 GB - 7 days", "data": "1 GB", "price": 468.84, "created_at": "2026-11-09 15:23:22", // ... "installation_guides": { "en": "https://www.airalo.com/help/getting-started-with-airalo" }, "text": null, "voice": null, "sims": [ { "created_at": "2026-11-09 15:23:22", "iccid": "8900000540463077957", "lpa": "lpa.airalo.com", "imsis": null, "qrcode": "LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741", // ... "apn_type": "automatic", "apn_value": "N/A", "is_roaming": true, "confirmation_code": null, "apn": { "ios": { "apn_type": "automatic", "apn_value": "N/A" }, "android": { "apn_type": "automatic", "apn_value": "N/A" } }, "msisdn": null, "direct_apple_installation_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741", "direct_android_installation_url": "https://esimsetup.android.com/esim_qrcode_provisioning?carddata=LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741", "sharing": { "access_code": 8803, "link": "https://esims.cloud/v8hy7-usgkq6wg" } } ], "total_price": 468.84, "retail_price": 468.84, "agency_currency": "DZD" } }Ví dụ đã rút gọn để hiển thị
- PASS Mã trạng thái là 200
- PASS $.data.package_id bằng france-in-7days-1gb
- PASS $.data.sims[0].iccid tồn tại
Tài liệu tham chiếu của GET /esims/bookings/{booking_id}/setup-instructions
Đọc dung lượng đã dùng, rồi nạp thêm
Khi du khách đã có eSIM, hãy đọc dữ liệu còn lại, hỏi gói nào có thể thêm vào đúng eSIM đó, rồi tạo lệnh nạp thêm. Dung lượng đã dùng được lưu đệm, nên một con số có thể cũ vài phút. Lịch sử nạp thêm nằm ở thanh bên và trong bản ghi.
Đọc dung lượng đã dùng
Lệnh gọi dung lượng đã dùng nhận ICCID của đơn và trả về
remainingvàtotaltính bằng megabyte, cùngstatusvà ngày hết hạn. Phản hồi đến từ bộ nhớ đệm, vàforce=truehỏi lại nhà cung cấp.Yêu cầu GET /esims/usage/{iccid} curl https://api.fx-port.com/api/v1/esims/usage/8900000540463077957 \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 160 ms · 261 B 200 OK { "environment": "sandbox", "success": true, "data": { "data": { "remaining": 1024, "total": 1024, "expired_at": "2026-11-16 15:23:29", "is_unlimited": false, "status": "ACTIVE", "remaining_voice": 0, "remaining_text": 0, "total_voice": 0, "total_text": 0 }, "meta": { "message": "success" } } }- PASS Mã trạng thái là 200
- PASS $.data.data.status bằng ACTIVE
- PASS $.data.data.remaining tồn tại
Liệt kê gói nạp thêm
Lệnh gọi này liệt kê các gói có thể thêm vào đúng eSIM này ngay hôm nay. Danh sách trống nghĩa là hiện không nạp thêm được. Hãy lấy
package_idcủa gói nạp thêm từ danh sách này, không bao giờ từ đơn gốc.Yêu cầu GET /esims/topup-packages/{iccid} curl https://api.fx-port.com/api/v1/esims/topup-packages/8900000540463077957 \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 240 ms · 1.1 KB 200 OK { "environment": "sandbox", "success": true, "data": { "data": [ { "id": "france-in-7days-1gb-topup", "package_id": "france-in-7days-1gb-topup", "type": "topup", "price": 468.84, "amount": 1024, "day": 7, "is_unlimited": false, "title": "1 GB - 7 days", "data": "1 GB", "short_info": null, // ... 12 more }, { // ... 22 more } ] } }Ví dụ đã rút gọn để hiển thị
- PASS Mã trạng thái là 200
- PASS $.data.data có 2 phần tử
- PASS $.data.data[0].type bằng topup
Tạo lệnh nạp thêm
Tạo lệnh nạp thêm nhận
package_idtừ danh sách đó và ICCID. Trên Live, số dư của bạn chỉ bị trừ sau khi nhà cung cấp chấp nhận. Ở sandbox,balancetrong phản hồi bằng không và không có khoản nào bị trừ.Yêu cầu POST /esims/topups curl https://api.fx-port.com/api/v1/esims/topups \ -H "Authorization: Bearer fxp_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "package_id": "france-in-7days-1gb-topup", "iccid": "8900000540463077957", "first_name": "John", "last_name": "Smith", "email": "[email protected]", "phone": "+15555550123" }'Phản hồi 200 OK · 900 ms · 682 B 200 OK { "environment": "sandbox", "success": true, "data": { "topup": { "code": "20261101-106853", "order_id": "20261101-106853", "package_id": "france-in-7days-1gb-topup", // ... 10 more }, "iccid": "8900000540463077957", "balance": { // ... 3 more } }, "booking_id": "FX-1793546625391", "message": "eSIM topup completed successfully", "balanceDebited": false, "balance_debited": false, "transactionCreated": false, "transaction_created": false, "payoutCreated": false, "payout_created": false }- PASS Mã trạng thái là 200
- PASS $.environment bằng sandbox
- PASS $.balance_debited bằng false
- PASS $.data.balance.current bằng 0
Đọc lịch sử nạp thêm
Lịch sử nạp thêm liệt kê các lần nạp thêm của một eSIM, mới nhất trước. Các lần nạp thêm không nằm trong danh sách đơn đặt, nên đây là nơi bạn tìm thấy chúng.
Yêu cầu GET /esims/bookings/{iccid}/topup-history curl https://api.fx-port.com/api/v1/esims/bookings/8900000540463077957/topup-history \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 130 ms · 615 B 200 OK { "environment": "sandbox", "success": true, "data": [ { "id": "bd6ff7d7-392f-4d56-8dea-4f0f3dff0af9", "booking_id": "FX-1793546625391", "order_id": "20261101-106853", "status": "confirmed", "currency": "DZD", "total_price": 468.84, "agency_commission": 50.24, "type": "topup", "package_name": "1 GB - 7 days", "iccid": "8900000540463077957", "customer_email": "[email protected]", "customer_first_name": "John", "customer_last_name": "Smith", "customer_phone": "+15555550123", "provider_name": "Airalo", // ... 4 more } ] }- PASS Mã trạng thái là 200
- PASS $.data[0].type bằng topup
Tài liệu tham chiếu của GET /esims/bookings/{iccid}/topup-history
Kiểm tra thiết bị, rồi đọc đơn đặt
Trước khi bán, hãy kiểm tra điện thoại của du khách có hỗ trợ eSIM không. Sau khi bán, hãy đọc các đơn đặt và kiểm tra mã đơn có phải của bạn không. Dung lượng đã dùng hàng loạt được liệt kê ở thanh bên.
Kiểm tra danh sách thiết bị
Lệnh gọi thiết bị tương thích trả về các thiết bị được biết là hỗ trợ eSIM, với
brand,modelvàos. Hãy tra điện thoại của du khách trước khi bán.Yêu cầu GET /esims/compatible-devices curl https://api.fx-port.com/api/v1/esims/compatible-devices \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 120 ms · 283 B 200 OK { "environment": "sandbox", "success": true, "data": [ { "model": "T803D", "os": "android", "brand": "Alcatel", "name": "V3 Ultra" }, { "model": "iPhone15,2", "os": "ios", "brand": "Apple", "name": "iPhone 14 Pro" } ], "meta": { "total_devices": 631, "cached_at": "2026-11-09T15:07:43.957236", "cache_age_days": 0.01 } }- PASS Mã trạng thái là 200
- PASS $.success bằng true
- PASS $.data[0].model tồn tại
Liệt kê đơn đặt
Danh sách đơn đặt trả về các đơn eSIM của đại lý bạn, mới nhất trước. Yêu cầu này chỉ lấy một đơn qua tham số
limit, vàpaginationcho biết có bao nhiêu đơn khớp và còn trang tiếp theo không.Yêu cầu GET /esims/bookings curl 'https://api.fx-port.com/api/v1/esims/bookings?limit=1' \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 150 ms · 714 B 200 OK { "environment": "sandbox", "success": true, "data": [ { "id": "639417b4-b103-4ece-bd5d-850315322278", "booking_id": "FX-1793546602916", "order_id": "20261101-106852", "status": "confirmed", "currency": "DZD", // ... 4 more "iccid": "8900000540463077957", // ... 9 more } ], "pagination": { "total": 61, "page": 1, "limit": 1, "pages": 61, "total_pages": 61, "has_more": true } }- PASS Mã trạng thái là 200
- PASS $.data có 1 phần tử
- PASS $.pagination.has_more bằng true
Kiểm tra quyền sở hữu
Lệnh kiểm tra quyền sở hữu trả
is_ownerlà true khi đơn thuộc đại lý của bạn. Đơn của đại lý khác và đơn không tồn tại nhận cùng một phản hồi, nên không thể dùng lệnh này để dò mã đơn.Yêu cầu GET /esims/bookings/{booking_id}/verify curl https://api.fx-port.com/api/v1/esims/bookings/FX-1793546602916/verify \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 90 ms · 167 B 200 OK { "environment": "sandbox", "isOwner": true, "is_owner": true, "userAgencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d", "bookingAgencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d" }- PASS Mã trạng thái là 200
- PASS $.is_owner bằng true
Tài liệu tham chiếu của GET /esims/bookings/{booking_id}/verify
Đọc dung lượng hàng loạt
Một lệnh gọi đọc dung lượng đã dùng của nhiều eSIM liệt kê trong
iccidsvà trả về một mục cho mỗi ICCID, mỗi mục cóstatusriêng. Luôn gửiiccids.Yêu cầu GET /esims/usage/bulk curl 'https://api.fx-port.com/api/v1/esims/usage/bulk?iccids=8900000540463077957' \ -H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK · 220 ms · 321 B 200 OK { "environment": "sandbox", "success": true, "data": [ { "iccid": "8900000540463077957", "data": { "data": { "remaining": 1024, "total": 1024, "expired_at": "2026-11-16 15:23:29", "is_unlimited": false, "status": "ACTIVE", "remaining_voice": 0, // ... 3 more }, "meta": { "message": "success" } }, "status": "success" } ] }- PASS Mã trạng thái là 200
- PASS $.data[0].status bằng success
Các sự cố và cách xử lý từng loại
Mọi lỗi dùng chung một nội dung, và phần tử đầu của errors có code ổn định. Các lệnh đặt đơn này cố tình thất bại, mỗi lệnh vì một lý do khác nhau và với một cách xử lý khác nhau.
Khóa chỉ đọc khi đặt đơn
Khóa chỉ đọc gọi lệnh đặt đơn bị từ chối với
403vàread_write_permission_required, trước khi nội dung được đọc. Hãy chuyển sang khóa đọc + ghi.Yêu cầu POST /esims/orders curl https://api.fx-port.com/api/v1/esims/orders \ -H "Authorization: Bearer fxp_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "package_id": "france-in-7days-1gb", "first_name": "John", "last_name": "Smith", "email": "[email protected]", "phone": "+15555550123", "description": "Order for John Smith" }'Phản hồi 403 Forbidden · 90 ms · 456 B 403 Forbidden { "environment": "sandbox", "success": false, "errors": [ { "code": "read_write_permission_required", "type": "permission_error", "title": "Read write permission required", "message": "This endpoint requires an API key with read_write permission.", "field": null, "details": {}, "documentation_url": "https://fx-port.com/docs/errors#read_write_permission_required" } ], "meta": { "request_id": "req_7f0c2e9a41b84d6e8a35c1d2", "status": 403 }, "request_id": "req_7f0c2e9a41b84d6e8a35c1d2" }- PASS Mã trạng thái là 403
- PASS Mã lỗi là read_write_permission_required
- PASS $.errors[0].type bằng permission_error
Địa chỉ email không hợp lệ
Giá trị không phải địa chỉ email bị từ chối với
400vàinvalid_email, vàfieldnêuemail. Hãy sửa giá trị trước khi gửi lại đơn: cùng yêu cầu sẽ thất bại như cũ.Yêu cầu POST /esims/orders curl https://api.fx-port.com/api/v1/esims/orders \ -H "Authorization: Bearer fxp_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "package_id": "france-in-7days-1gb", "first_name": "John", "last_name": "Smith", "email": "traveler-at-example.com", "phone": "+15555550123", "description": "Order for John Smith" }'Phản hồi 400 Bad Request · 100 ms · 381 B 400 Bad Request { "environment": "sandbox", "success": false, "errors": [ { "code": "invalid_email", "type": "validation_error", "title": "Invalid email", "message": "email is not a valid email address", "field": "email", "details": {}, "documentation_url": "https://fx-port.com/docs/errors#invalid_email" } ], "meta": { "request_id": "req_7f0c2e9a41b84d6e8a35c1d2", "status": 400 }, "request_id": "req_7f0c2e9a41b84d6e8a35c1d2" }- PASS Mã trạng thái là 400
- PASS Mã lỗi là invalid_email
- PASS $.errors[0].field bằng email
Đơn trùng lặp
Đơn cho gói đang được xử lý bị từ chối với
409vàduplicate_request. Đừng gửi lại ngay: hãy tra đơn đặt trước, và chỉ đặt lại nếu chưa có đơn nào được tạo.Yêu cầu POST /esims/orders curl https://api.fx-port.com/api/v1/esims/orders \ -H "Authorization: Bearer fxp_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "package_id": "france-in-7days-1gb", "first_name": "John", "last_name": "Smith", "email": "[email protected]", "phone": "+15555550123", "description": "Order for John Smith" }'Phản hồi 409 Conflict · 110 ms · 423 B 409 Conflict { "environment": "sandbox", "success": false, "errors": [ { "code": "duplicate_request", "type": "conflict", "title": "Duplicate request", "message": "An identical order is already being processed. Please wait before retrying.", "field": null, "details": {}, "documentation_url": "https://fx-port.com/docs/errors#duplicate_request" } ], "meta": { "request_id": "req_7f0c2e9a41b84d6e8a35c1d2", "status": 409 }, "request_id": "req_7f0c2e9a41b84d6e8a35c1d2" }- PASS Mã trạng thái là 409
- PASS Mã lỗi là duplicate_request
- PASS $.errors[0].type bằng conflict
Quá nhiều yêu cầu
Vượt giới hạn mỗi phút, lệnh gọi bị từ chối với
429vàrate_limit_exceeded, và headerRetry-Aftercho biết phải chờ bao nhiêu giây. Sau đó hãy thử lại với backoff.Yêu cầu POST /esims/orders curl https://api.fx-port.com/api/v1/esims/orders \ -H "Authorization: Bearer fxp_test_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "package_id": "france-in-7days-1gb", "first_name": "John", "last_name": "Smith", "email": "[email protected]", "phone": "+15555550123", "description": "Order for John Smith" }'Phản hồi 429 Too Many Requests · 80 ms · 504 B 429 Too Many Requests Retry-After: 12 { "environment": "sandbox", "success": false, "errors": [ { "code": "rate_limit_exceeded", "type": "rate_limit_error", "title": "Rate limit exceeded", "message": "Too many requests hit the API too quickly. Please retry your request after the time specified in the `ratelimit-reset` header.", "field": null, "details": { "retry_after": 12 }, "documentation_url": "https://fx-port.com/docs/errors#rate_limit_exceeded" } ], "meta": { "request_id": "req_7f0c2e9a41b84d6e8a35c1d2", "status": 429 }, "request_id": "req_7f0c2e9a41b84d6e8a35c1d2" }- PASS Mã trạng thái là 429
- PASS Mã lỗi là rate_limit_exceeded
- PASS Có header Retry-After
- PASS $.errors[0].details.retry_after bằng 12
Từ danh mục gói đến du khách có kết nối trong năm bước
Tích hợp chỉ là một lộ trình ngắn: đọc danh mục gói, tạo đơn, giao eSIM cho du khách, theo dõi dung lượng đã dùng và nạp thêm khi hết dữ liệu. Chỉ đơn đặt và lệnh nạp thêm làm thay đổi dữ liệu. Mọi lệnh gọi khác chỉ đọc.
Đọc danh mục gói của một điểm đến
Liệt kê các gói của một quốc gia, với giá đã tính sẵn theo tiền tệ của đại lý, rồi giữ lại package_id của gói du khách chọn. Luôn gửi country: toàn bộ danh mục là một phản hồi rất lớn và không phân trang. Hãy đọc mã gói từ phản hồi thay vì viết cứng, vì danh mục thay đổi.
Yêu cầu
curl 'https://api.fx-port.com/api/v1/esims/packages?country=france&type=local' \
-H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK
{
"environment": "sandbox",
"success": true,
"endpoint": "/packages",
"data": [
{
"id": "france-in-7days-1gb",
"package_id": "france-in-7days-1gb",
"type": "sim",
"price": 402.5,
"base_price": 402.5,
// ... 28 more
"total_price": 468.84,
"balance_debit_amount": 418.6,
"b2b_price": 418.6,
"agency_commission": "12 %",
"commission_rate": 12,
"currency": "DZD",
// ... 2 more
},
// ...
],
"meta": {
"total_packages": 12,
"filters_applied": {
// ... 2 more
},
"locale": "en",
"agency_currency": "DZD",
"currency": "DZD",
"supplier_currency": "USD",
"exchange_rate": 250,
"commission_percentage": "12 %",
"commission_rate": 12
}
}Tạo đơn
Gửi package_id cùng địa chỉ email và số điện thoại của du khách. Một đơn tạo đúng một eSIM, và trên Live đơn trừ vào số dư đại lý của bạn. Hãy giữ booking_id và ICCID trong phản hồi, vì mọi lệnh gọi sau đó đều cần một trong hai.
Yêu cầu
curl https://api.fx-port.com/api/v1/esims/orders \
-H "Authorization: Bearer fxp_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"package_id": "france-in-7days-1gb",
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"phone": "+15555550123",
"description": "Order for John Smith"
}'Phản hồi 200 OK
{
"environment": "sandbox",
"success": true,
"data": {
"order": {
"code": "20261101-106852",
"order_id": "20261101-106852",
"package_id": "france-in-7days-1gb",
// ... 17 more
},
"sim": {
// ... 4 more
"qrcode": "LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741",
// ... 7 more
"sharing": {
"access_code": 8803,
"link": "https://esims.cloud/v8hy7-usgkq6wg"
}
},
"iccid": "8900000540463077957"
},
"booking_id": "FX-1793546602916",
"message": "eSIM order placed successfully",
"balanceDebited": false,
"balance_debited": false,
"transactionCreated": false,
"transaction_created": false,
"payoutCreated": false,
"payout_created": false
}| Trường | Chứa gì |
|---|---|
booking_id | Mã tham chiếu FX-Port của đơn. Hãy giữ lại để dùng cho dữ liệu cài đặt, kiểm tra quyền sở hữu và hồ sơ của bạn. |
data.iccid | Mã định danh của eSIM. Dung lượng đã dùng, nạp thêm và hướng dẫn cài đặt đều tra cứu theo ICCID. |
data.sim.qrcode data.sim.qrcode_url | Chuỗi kích hoạt mà mã QR mã hóa, cùng liên kết tới hình ảnh mã QR. |
data.sim.direct_apple_installation_url data.sim.sharing | Liên kết bắt đầu cài đặt trên iPhone, và trang chia sẻ nơi du khách mở eSIM bằng mã truy cập. Lệnh gọi dữ liệu cài đặt bổ sung liên kết cho Android. |
PENDING-, và dữ liệu có thể lấy từ lệnh gọi dữ liệu cài đặt khi nhà cung cấp đã có.Giao eSIM cho du khách
Phản hồi chứa mã QR và chuỗi kích hoạt của mã đó, nên bạn có thể hiển thị trên màn hình của mình. FX-Port cũng yêu cầu nhà cung cấp gửi email kèm mã QR và liên kết chia sẻ tới địa chỉ của du khách, nên bạn không phải chuyển tiếp. Lệnh gọi dữ liệu cài đặt trả lại cùng dữ liệu đó vào lúc sau, kèm các bước cài đặt.
Yêu cầu
curl https://api.fx-port.com/api/v1/esims/bookings/FX-1793546602916/setup-instructions \
-H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK
{
"environment": "sandbox",
"success": true,
"data": {
"code": "20261101-106852",
"order_id": "20261101-106852",
"currency": "DZD",
"package_id": "france-in-7days-1gb",
"quantity": 1,
"type": "sim",
"description": "Order for John Smith",
"esim_type": "local",
"validity": 7,
"package": "KPN France Data only-1 GB - 7 days",
"data": "1 GB",
// ... 5 more
"sims": [
{
"created_at": "2026-11-09 15:23:22",
"iccid": "8900000540463077957",
// ... 2 more
"qrcode": "LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741",
// ... 6 more
"direct_apple_installation_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741",
// ... 2 more
}
],
// ... 3 more
}
}Theo dõi dung lượng đã dùng
Đọc dữ liệu còn lại và ngày hết hạn của một eSIM theo ICCID. Phản hồi được lưu đệm tối đa 15 phút, vì vậy hãy dùng cho một màn hình hoặc một lời nhắc, không dùng làm đồng hồ đo.
Yêu cầu
curl https://api.fx-port.com/api/v1/esims/usage/8900000540463077957 \
-H "Authorization: Bearer fxp_test_YOUR_KEY"Phản hồi 200 OK
{
"environment": "sandbox",
"success": true,
"data": {
"data": {
"remaining": 1024,
"total": 1024,
"expired_at": "2026-11-16 15:23:29",
"is_unlimited": false,
"status": "ACTIVE",
"remaining_voice": 0,
"remaining_text": 0,
"total_voice": 0,
"total_text": 0
},
"meta": {
"message": "success"
}
}
}Nạp thêm dữ liệu khi hết
Liệt kê các gói có thể thêm vào đúng eSIM này, rồi tạo lệnh nạp thêm bằng một trong các gói đó. Nếu danh sách trống, eSIM hiện không nạp thêm được và du khách cần một eSIM mới.
Yêu cầu
curl https://api.fx-port.com/api/v1/esims/topups \
-H "Authorization: Bearer fxp_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"package_id": "france-in-7days-1gb-topup",
"iccid": "8900000540463077957",
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"phone": "+15555550123"
}'Phản hồi 200 OK
{
"environment": "sandbox",
"success": true,
"data": {
"topup": {
"code": "20261101-106853",
"order_id": "20261101-106853",
"package_id": "france-in-7days-1gb-topup",
"package": "KPN France Data only-1 GB - 7 days",
"data": "1 GB",
"validity": 7,
"price": 468.84,
// ... 6 more
},
"iccid": "8900000540463077957",
"balance": {
"previous": 0,
"current": 0,
"currency": "DZD"
}
},
"booking_id": "FX-1793546625391",
"message": "eSIM topup completed successfully",
"balanceDebited": false,
"balance_debited": false,
"transactionCreated": false,
"transaction_created": false,
"payoutCreated": false,
"payout_created": false
}Giá, hoa hồng và số dư của bạn
Mỗi gói đi kèm các trường về tiền, được tính trên máy chủ theo tiền tệ của đại lý. Giá trong nội dung yêu cầu bị bỏ qua, nên đơn luôn được tạo theo giá máy chủ tính.
| Trường | Chứa gì |
|---|---|
base_price price | Giá gói trước hoa hồng của bạn. Đây không phải số tiền trừ vào số dư của bạn. |
total_price retail_price | Giá cần thu của du khách, đã gồm hoa hồng của bạn. |
balance_debit_amount b2b_price | Số tiền rời khỏi số dư đại lý khi bạn đặt gói trên Live. Hãy đọc giá trị này, đừng tự tính. |
agency_commission commission_rate | Tỷ lệ hoa hồng của bạn, dạng văn bản và dạng số. Đơn đặt trả về hoa hồng của bạn dưới dạng số tiền. |
Trong ví dụ về danh mục gói, du khách trả 468.84 DZD. Một đơn trên Live trừ 418.60 DZD vào số dư của bạn, và phần chênh lệch, 50.24 DZD, là hoa hồng của bạn.
Tỷ lệ hoa hồng thuộc về đại lý của bạn
Tỷ lệ hoa hồng được trả về cùng mỗi gói, và không giống nhau ở mọi đại lý. Một đại lý doanh nghiệp có hợp đồng có thể có tỷ lệ bằng không, khi đó giá tổng bằng số tiền trừ.
Hãy đọc các trường, đừng tự dựng lại
Số tiền trừ có thể cao hơn giá gốc, vì đã gồm các khoản riêng của đại lý bạn. Vì vậy hãy đọc balance_debit_amount và không bao giờ tính từ base_price. Từ price là giá gốc trong danh mục nhưng là giá bán lẻ trong đơn đặt, gói nạp thêm và dữ liệu cài đặt: hãy dùng base_price và total_price ở mọi nơi, sự mơ hồ sẽ biến mất.
Định giá theo tiền tệ của đại lý
Mọi số tiền đều đã được quy đổi sang tiền tệ của đại lý, dù nhà cung cấp dùng tiền tệ nào. Phản hồi cũng cho biết tiền tệ của nhà cung cấp và tỷ giá, để bạn tự kiểm chứng tỷ giá và không cần quy đổi lại.
Sau khi bán: dung lượng đã dùng, nạp thêm và dữ liệu cài đặt
Một lần bán không kết thúc ở đơn đặt. Các lệnh gọi này giữ du khách luôn kết nối, và chỉ áp dụng cho eSIM mà đại lý của bạn đã đặt trong cùng môi trường với khóa của bạn.
Đọc dung lượng đã dùng và độ mới của số liệu
Lệnh gọi này trả về dữ liệu còn lại, hạn mức, trạng thái và ngày hết hạn của một eSIM, hoặc của tối đa 50 eSIM trong một lần gọi. FX-Port giữ phản hồi gần nhất tối đa 15 phút để bảo vệ giới hạn tốc độ của nhà cung cấp, nên một con số có thể cũ đến mức đó. Truyền force=true để hỏi lại nhà cung cấp, chẳng hạn ngay sau khi nạp thêm. Đừng làm vậy ở mọi yêu cầu, vì nhà cung cấp giới hạn tần suất đọc. Nếu nhà cung cấp không trả lời được, bạn nhận số liệu gần nhất đã biết, được đánh dấu là cũ.
Nạp thêm dữ liệu: hỏi trước, tạo sau
Nạp thêm gồm hai lệnh gọi. Trước tiên liệt kê các gói có thể thêm vào đúng eSIM này, rồi tạo lệnh nạp thêm bằng một mã gói được trả về. Đừng dùng lại mã gói của đơn gốc, và đừng giữ sẵn gói nạp thêm để dùng sau: hãy hỏi lại khi du khách muốn nạp thêm. Nạp thêm bổ sung dữ liệu vào eSIM chứ không thay thế phần còn lại, nên hãy đọc kết quả qua lệnh gọi dung lượng đã dùng với force=true.
Khi không thể nạp thêm
Nhà cung cấp chọn nhà mạng phục vụ một quốc gia, và trong một số ít trường hợp họ đổi nhà mạng. Khi đó eSIM có thể tiếp tục hoạt động đến khi hết hạn, nhưng gói của nó không còn nạp thêm được. Danh sách gói nạp thêm trả về rỗng. Nếu nhà cung cấp từ chối lệnh nạp thêm, số dư của bạn không bị ảnh hưởng và lần thử được lưu thành một đơn thất bại. Phản hồi là supplier_error để bạn xử lý.
Dữ liệu cài đặt và các bước cài đặt
Lệnh gọi dữ liệu cài đặt trả về mã QR, dữ liệu kích hoạt, liên kết cài đặt và các bước cài đặt của một đơn bất cứ khi nào bạn cần. Lệnh gọi hướng dẫn trả về các bước theo từng hệ điều hành, bằng ngôn ngữ bạn yêu cầu. Các bước này là văn bản chung của nhà cung cấp, nên hãy hiển thị chúng cạnh mã QR của đơn. Chỉ hiển thị cả hai cho du khách sở hữu eSIM.
Đơn đặt, lịch sử nạp thêm và quyền sở hữu
Danh sách đơn đặt trả về các đơn eSIM của đại lý bạn trong môi trường của khóa, mới nhất trước. Bạn có thể tìm theo mã đơn, tên du khách, địa chỉ email, tên gói hoặc ICCID. Các lần nạp thêm không nằm trong danh sách đó: hãy đọc chúng bằng lịch sử nạp thêm của một eSIM. Trước khi dựng liên kết hay màn hình quanh một mã đơn, lệnh kiểm tra quyền sở hữu cho bạn biết đơn đó có phải của bạn không. Đơn của đại lý khác và đơn không tồn tại nhận cùng một phản hồi.
Mọi endpoint eSIM, kèm OpenAPI, Postman và mã mẫu
API eSIM có 12 endpoint dưới một Base URL. Mỗi dòng mở trang tham chiếu của lệnh gọi đó, với các trường yêu cầu, phản hồi, lỗi và ví dụ bằng 9 ngôn ngữ.
| Endpoint | Chức năng | Khóa |
|---|---|---|
GET /api/v1/esims/packages | Liệt kê gói của một quốc gia hoặc khu vực, với giá đã tính sẵn theo tiền tệ của đại lý. Luôn gửi quốc gia: toàn bộ danh mục rất lớn và không phân trang. | Đọc |
GET /api/v1/esims/compatible-devices | Các thiết bị được biết là hỗ trợ eSIM, để kiểm tra trước khi du khách mua. | Đọc |
POST /api/v1/esims/orders | Tạo một eSIM từ một gói cho du khách và cấp phát tại nhà cung cấp. Trên Live, lệnh này trừ vào số dư đại lý. | Đọc + ghi |
GET /api/v1/esims/topup-packages/{iccid} | Các gói có thể thêm vào đúng một eSIM ngay hôm nay. Danh sách trống nghĩa là hiện không nạp thêm được. | Đọc |
POST /api/v1/esims/topups | Thêm một gói nạp thêm vào eSIM hiện có. Trên Live, số dư của bạn chỉ bị trừ sau khi nhà cung cấp chấp nhận. | Đọc + ghi |
GET /api/v1/esims/usage/{iccid} | Dữ liệu còn lại, hạn mức, trạng thái và ngày hết hạn của một eSIM. Phản hồi có thể cũ đến 15 phút. | Đọc |
GET /api/v1/esims/usage/bulk | Dung lượng đã dùng của tối đa 50 eSIM trong một lần gọi, mỗi ICCID một mục, mỗi mục có trạng thái riêng. | Đọc |
GET /api/v1/esims/bookings | Các đơn eSIM của đại lý bạn, mới nhất trước, có tìm kiếm và phân trang. Các lần nạp thêm không nằm trong danh sách này. | Đọc |
GET /api/v1/esims/bookings/{iccid}/topup-history | Các lần nạp thêm của một eSIM, mới nhất trước. Danh sách trống khi eSIM chưa có lần nào. | Đọc |
GET /api/v1/esims/bookings/{booking_id}/verify | Kiểm tra mã đơn có thuộc đại lý của bạn không, trước khi dựng liên kết hay màn hình quanh mã đó. | Đọc |
GET /api/v1/esims/bookings/{booking_id}/setup-instructions | Mã QR, dữ liệu kích hoạt, liên kết cài đặt và các bước cài đặt của một đơn, dạng JSON. | Đọc |
GET /api/v1/esims/instructions/{iccid} | Hướng dẫn cài đặt từng bước cho một ICCID, theo hệ điều hành, bằng ngôn ngữ bạn yêu cầu. | Đọc |
OpenAPI 3.1
Một tệp mô tả mọi endpoint và mọi trường. Hãy tạo client từ tệp này, nhập vào công cụ API hoặc đưa cho trợ lý lập trình.
Bộ sưu tập Postman
Bộ sưu tập eSIM bao phủ cả 12 endpoint trong các thư mục theo từng giai đoạn của một lần bán. Bộ này không chứa khóa, nên hãy thêm khóa của bạn.
Mã mẫu bằng 9 ngôn ngữ
Mỗi trang tham chiếu in yêu cầu bằng cURL, Node.js, Python, PHP, Go, Java, C#, Swift và Kotlin, được tạo từ mô tả OpenAPI. Mọi yêu cầu eSIM đều có sẵn trong tất cả các ngôn ngữ đó.
Tài liệu cho trợ lý AI
llms.txt và llms-full.txt đưa tài liệu cho trợ lý AI dưới dạng văn bản thuần, và mọi trang tài liệu đều đọc được dưới dạng Markdown bằng cách thêm .md vào địa chỉ.
Xây cho môi trường thực tế: khóa, lỗi, thử lại và lưu đệm
Một tích hợp eSIM được đánh giá ở môi trường thực tế qua xác thực, lỗi, thử lại, lưu đệm và giới hạn tốc độ. Dưới đây là những điều cần biết về từng mục.
Một Base URL, hai loại khóa
Mỗi yêu cầu mang một khóa dưới dạng Bearer token trong header Authorization. Tiền tố cho biết khóa dùng ở đâu: fxp_test_ cho sandbox và fxp_live_ cho Live. Cả hai cùng gọi một Base URL, và mỗi phản hồi JSON nêu môi trường nó đến từ trong environment. Khóa thuộc về máy chủ của bạn, không bao giờ để trong trình duyệt hay ứng dụng. FX-Port chỉ lưu mã băm của mỗi khóa, nên khóa đã mất không thể hiển thị lại. Thay đổi đối với khóa có thể mất vài phút để có hiệu lực.
Khóa nào gọi được lệnh nào
Khóa chỉ đọc có thể liệt kê gói, kiểm tra thiết bị, đọc dung lượng đã dùng và đọc đơn đặt. Tạo đơn hoặc lệnh nạp thêm cần khóa đọc + ghi, và khóa chỉ đọc thử làm vậy sẽ nhận read_write_permission_required. Mọi khóa đều có thể giới hạn theo danh sách địa chỉ IP, và lệnh gọi từ địa chỉ khác nhận ip_not_allowed. Hãy dùng khóa chỉ đọc ở nơi mã chỉ hiển thị kết quả.
Một định dạng lỗi cho mọi sự cố
Lệnh gọi thất bại trả về mảng errors. Phần tử đầu tiên có code ổn định, type cho biết cách xử lý và field gây lỗi. Hãy kiểm tra mã, đừng kiểm tra thông điệp. Danh sách lỗi dùng chung cho chuyến bay, khách sạn, eSIM và tài khoản có 180 mã. Khi nhà cung cấp từ chối một đơn hoặc một lệnh nạp thêm, phản hồi là supplier_error mang theo trạng thái HTTP riêng của nhà cung cấp. Không có khoản nào bị trừ và một đơn thất bại được lưu lại. Ngay sau khi khởi động lại, danh mục gói và danh sách thiết bị có thể trả 202 với success là false: hãy chờ vài giây rồi hỏi lại.
Thử lại mà không đặt hai lần
FX-Port không có khóa idempotency, nên không có header Idempotency-Key để gửi. Lệnh đọc có thể lặp lại an toàn; tạo đơn hoặc lệnh nạp thêm thì không. FX-Port từ chối bản trùng rõ ràng bằng 409 và duplicate_request: một đơn cho gói đang được xử lý. Trên Live, FX-Port còn từ chối cùng gói đó được đặt lại trong vòng 60 giây kể từ đơn đã xác nhận gần nhất của đại lý bạn, dù du khách là ai. Đơn thường được trả lời trong vài giây, nhưng nhà cung cấp chậm có thể mất lâu hơn nhiều. Nếu lệnh gọi hết thời gian chờ hoặc kết nối đứt, đừng gửi lại đơn ngay, vì eSIM có thể đã tồn tại. Hãy tìm bằng tham số search của danh sách đơn đặt, dùng địa chỉ email của du khách, và chỉ đặt lại nếu chưa có gì được tạo.
Không có webhook: hãy hỏi khi cần
FX-Port không gọi một URL nào của bạn, ở sandbox hay Live. Một đơn trả lời bằng eSIM, hoặc bằng giá trị giữ chỗ PENDING- khi nhà cung cấp chưa trả eSIM. Mọi thứ khác bạn hỏi khi cần: dữ liệu cài đặt, dung lượng đã dùng hoặc danh sách đơn đặt.
Lưu đệm và tốc độ
Dung lượng đã dùng được giữ tối đa 15 phút và danh sách gói nạp thêm được giữ vài phút, còn force=true bỏ qua bộ nhớ đệm. Danh mục gói không lọc là một phản hồi rất lớn và không phân trang, nên hãy gửi country và chấp nhận nén bằng Accept-Encoding: gzip. Tên gói trả về theo ngôn ngữ của tham số locale; yêu cầu đầu tiên bằng ngôn ngữ khác tiếng Anh sẽ chậm hơn, vì văn bản được lấy lúc đó và lưu đệm cho các lần sau.
Giới hạn tốc độ
Giới hạn được tính theo từng khóa và từng phút, chia thành hai nhóm, và mọi phản hồi đều mang ratelimit-limit và ratelimit-remaining để bạn giảm tốc trước khi bị từ chối. Sau một lỗi 429, hãy chờ số giây ghi trong Retry-After rồi thử lại với backoff lũy thừa và jitter. Nếu một khóa hoặc một đại lý chạy quá nhiều đơn hoặc lệnh nạp thêm cùng lúc, phản hồi có thể là concurrency_limit_exceeded.
| Loại lệnh gọi | Mỗi phút |
|---|---|
| Tạo đơn và lệnh nạp thêm | 1,200 |
| Mọi endpoint eSIM khác | 6,000 |
Hiện tại, mức trần cho số đơn và lệnh nạp thêm chạy cùng lúc đang ở chế độ quan sát: được đếm nhưng chưa áp dụng, nên chưa có gì bị từ chối vì nó, và changelog sẽ thông báo ngày bắt đầu áp dụng. Hãy xem các con số này là chính sách hiện hành chứ không phải cam kết. Khóa sandbox có cùng bộ đếm mỗi phút với khóa live, nên hãy lên lịch kiểm thử tải thay vì chạy trong vòng lặp.
Tên và phiên bản
Các trường của yêu cầu viết theo snake_case, chẳng hạn first_name và agent_id. Các cách viết cũ vẫn dùng được: user_id được đọc như agent_id và thêm một mục warnings, còn customer_email được chấp nhận như email mà không có cảnh báo. Nhiều phản hồi giữ khóa cũ bên cạnh bản snake_case cùng giá trị, chẳng hạn order_id cạnh code, và ?naming=snake chỉ trả về các khóa snake_case. Phiên bản nằm trong đường dẫn, /api/v1: thay đổi phá vỡ tương thích sẽ dùng tiền tố mới, còn trường và cách viết mới chỉ là bổ sung.
Bắt đầu ở sandbox miễn phí, rồi chuyển sang Live
Mọi thứ trên trang này hiện đều chạy được ở sandbox. Khóa sandbox tự tạo được và miễn phí, và không bao giờ chạm vào số dư thật của bạn.
Tạo tài khoản
Đăng ký tài khoản FX-Port. Khóa sandbox miễn phí, và các đặt chỗ trên sandbox không phát sinh khoản phí thực nào.
Tạo khóa sandbox
Tại trang API trong bảng điều khiển, hãy tạo một khóa bắt đầu bằng
fxp_test_. Khóa chỉ đọc có thể tìm kiếm và đọc dữ liệu; khóa đọc + ghi còn tạo được các đặt chỗ thử nghiệm.Gửi yêu cầu đầu tiên
Chỉ có một base URL, và khóa được đặt trong header
Authorizationdưới dạng bearer token. Hướng dẫn bắt đầu nhanh sẽ đưa bạn qua lần gọi đầu tiên.Chuyển sang Live khi bạn sẵn sàng
Thay bằng khóa
fxp_live_. Live hoạt động khi đại lý của bạn được phê duyệt; trước đó API trả về403 agency_not_active. Các đặt chỗ thực được thanh toán từ số dư đã nạp tiền.
Yêu cầu danh mục gói đầu tiên bằng cURL. Tài liệu in cùng yêu cầu này bằng mọi ngôn ngữ được hỗ trợ.
Yêu cầu
curl 'https://api.fx-port.com/api/v1/esims/packages?country=france&type=local' \
-H "Authorization: Bearer fxp_test_YOUR_KEY"Hướng dẫn bắt đầu nhanh: lệnh sandbox đầu tiên
Sandbox làm gì
Một đơn ở sandbox tạo một eSIM thử thật tại nhà cung cấp, với mã kích hoạt giả, nên không thể cài lên điện thoại. Không có khoản nào bị trừ, và phản hồi nói rõ điều đó: balanceDebited, transactionCreated và payoutCreated đều là false. Lệnh nạp thêm trả về số dư bằng không. Dung lượng đã dùng là cố định: eSIM mới hiển thị đủ hạn mức và trạng thái ACTIVE. Đơn đặt ở sandbox chỉ khóa sandbox mới thấy.
Chỉ Live mới kiểm thử được gì
Kiểm tra số dư, kiểm tra trùng lặp và khóa số dư chỉ chạy trên Live. Vì vậy các phản hồi 402 với insufficient_balance, 409 cho cùng gói được đặt lại trong vòng 60 giây, và 503 với balance_lock_timeout không bao giờ xuất hiện ở sandbox. Hãy viết cách xử lý chúng dựa trên danh sách mã lỗi.
Chuyển sang Live
Khóa Live gắn với việc duyệt đại lý: cho đến khi đại lý của bạn được duyệt, khóa Live trả agency_not_active và khóa sandbox vẫn hoạt động. Đơn Live được thanh toán từ số dư đại lý đã nạp tiền. Chuyển sang Live chỉ đổi khóa, không đổi mã, vì sandbox và Live dùng chung một Base URL.
Ai xây dựng trên API eSIM
Mỗi nhóm khách hàng dựa vào một phần khác nhau của cùng các lệnh gọi.
Đại lý bán chuyến đi
Đại lý bán eSIM bên cạnh chuyến bay và khách sạn. Họ đặt bằng chính địa chỉ email của du khách, để nhà cung cấp gửi mã QR và liên kết chia sẻ, và đọc dung lượng đã dùng khi du khách hỏi. Tỷ lệ hoa hồng được trả về cùng mỗi gói, và agent_id ghi lại người dùng nào của đại lý bạn đã đặt đơn.
OTA và sàn giao dịch
Sàn giao dịch dựng trang duyệt gói trước: từng quốc gia một, gói nội địa hoặc khu vực, nhà mạng và hạn mức dữ liệu của từng gói, cùng bước kiểm tra thiết bị trước khi du khách mua. Một màn hình liệt kê các eSIM của du khách có thể đọc dung lượng đã dùng của tối đa 50 eSIM trong một lần gọi.
Đội công nghệ du lịch và doanh nghiệp
Đội công nghệ du lịch và bộ phận du lịch công tác của doanh nghiệp tự xây công cụ đặt chỗ. Mọi thứ cần để bắt đầu đều công khai: tệp OpenAPI, bộ sưu tập Postman và tài liệu văn bản thuần mà trợ lý lập trình AI đọc được, nên nguyên mẫu đầu tiên xuất phát từ hợp đồng thật.
API eSIM: câu hỏi thường gặp
API eSIM của FX-Port là gì và dành cho ai?
Đây là một REST API giúp đại lý du lịch, OTA hoặc đơn vị bán lại bán eSIM dữ liệu du lịch từ một lần tích hợp. Bạn liệt kê các gói của một điểm đến với giá theo tiền tệ của đại lý và đặt một gói cho du khách. Bạn gửi mã QR cho du khách, theo dõi dung lượng đã dùng và nạp thêm dữ liệu. Mọi thứ là JSON qua HTTPS, và một tệp OpenAPI mô tả từng endpoint.
Có sandbox miễn phí không, và lấy khóa bằng cách nào?
Có. Hãy tạo tài khoản FX-Port, mở trang API trong bảng điều khiển và tạo khóa sandbox; bạn tự làm được, không mất phí. Một đơn ở sandbox tạo eSIM thử với mã kích hoạt giả, nên không thể cài lên điện thoại. Không có khoản nào bị trừ khỏi số dư của bạn. Sandbox và Live dùng chung một Base URL, nên mã bạn thử nghiệm cũng là mã bạn đưa vào vận hành.
Chuyển sang Live cần những gì?
Đại lý của bạn phải được duyệt thì khóa Live mới hoạt động. Cho đến lúc đó, khóa Live bị từ chối và khóa sandbox vẫn dùng được. Đơn Live được thanh toán từ số dư đại lý đã nạp tiền, điều mà sandbox không bao giờ chạm tới, và mọi khóa đều có thể giới hạn theo danh sách địa chỉ IP. Chuyển đổi chỉ là đổi khóa; mỗi phản hồi đều nêu môi trường nó đến từ.
Tôi có thể bán gói của những quốc gia nào?
Có gói cho 190+ quốc gia, và các gói khu vực nằm dưới khu vực của chúng. Các gói khác nhau về hạn mức dữ liệu, thời hạn, nhà mạng và khả năng nạp thêm. Hãy đọc các trường này và mã gói từ phản hồi danh mục thay vì viết cứng. Hãy hỏi từng quốc gia một, vì toàn bộ danh mục là một phản hồi rất lớn. Một danh sách thiết bị riêng cho phép kiểm tra điện thoại của du khách trước khi bán.
Du khách nhận eSIM bằng cách nào?
Phản hồi của đơn chứa mã QR, chuỗi kích hoạt của mã đó, liên kết cài đặt cho iPhone và một trang chia sẻ. Bạn có thể hiển thị chúng trên màn hình của mình. FX-Port cũng yêu cầu nhà cung cấp gửi email kèm mã QR và liên kết chia sẻ tới địa chỉ của du khách ngay khi eSIM được tạo. Nếu nhà cung cấp chưa trả eSIM, đơn vẫn tồn tại và dữ liệu có thể lấy sau từ lệnh gọi dữ liệu cài đặt.
Giá, hoa hồng và số dư của tôi liên hệ với nhau thế nào?
Mỗi gói đi kèm các trường về tiền sau, tính theo tiền tệ của đại lý: giá gốc trước hoa hồng, giá tổng thu của du khách, số tiền trừ khỏi số dư và tỷ lệ hoa hồng của bạn. Hoa hồng của bạn bằng giá tổng trừ đi số tiền bị trừ. Hãy đọc các trường này thay vì tự dựng lại, vì số tiền trừ là riêng của đại lý bạn. Ở sandbox không có khoản nào bị trừ; trên Live, khoản trừ rời khỏi số dư đại lý.
Tôi có nạp thêm cho eSIM được không, và xem phần còn lại bằng cách nào?
Được, bằng hai lệnh gọi: liệt kê các gói có thể thêm vào đúng eSIM đó, rồi tạo lệnh nạp thêm bằng một trong các gói. Không phải lúc nào cũng nạp thêm được, vì nhà cung cấp có thể đổi nhà mạng của một quốc gia. Khi đó danh sách trống nghĩa là du khách cần một eSIM mới. Dung lượng đã dùng được lưu đệm tối đa 15 phút, nên hãy xem đó là số liệu gần đây, và một lệnh gọi đọc được tối đa 50 eSIM.
Lỗi được báo cáo thế nào, và có webhook không?
Lỗi được trả về trong một định dạng với mã lỗi ổn định, và chương trình của bạn nên kiểm tra mã đó, không phải nội dung thông điệp. Lệnh đọc lặp lại an toàn với backoff. Tạo đơn hoặc lệnh nạp thêm thì khác: không có khóa idempotency, nên sau khi hết thời gian chờ hãy tra đơn đặt trước khi thử lại. FX-Port chỉ từ chối một đơn trùng lặp hiển nhiên, chẳng hạn cùng gói đặt hai lần trong vòng 60 giây trên Live. Không có webhook.
Tôi có thể hủy hoặc hoàn tiền một đơn eSIM qua API không?
Không. API không có endpoint để hủy hoặc hoàn tiền một đơn eSIM. Mỗi đơn tạo đúng một eSIM, vì vậy hãy kiểm tra gói và thông tin du khách trước khi gửi. Nếu nhà cung cấp từ chối đơn, không có khoản nào bị trừ và một đơn thất bại được lưu lại. Với sự cố của một đơn cụ thể, hãy viết cho đội phát triển và nêu mã đơn.
Tôi cần gì để bắt đầu, và công cụ nào hỗ trợ?
Bạn cần một khóa sandbox và một HTTP client. Tài liệu bổ sung tệp OpenAPI 3.1, bộ sưu tập Postman, mã mẫu bằng 9 ngôn ngữ và bản xuất văn bản thuần cho trợ lý AI. Hãy giữ khóa trên máy chủ của bạn, không để trong trình duyệt hay ứng dụng. Phần tốn thời gian hơn là quy trình thanh toán của riêng bạn, việc gửi mã QR cho du khách và xử lý lỗi.
Các API khác của FX-Port
Một eSIM thường đi cùng một chuyến đi. Chuyến bay và khách sạn dùng cùng khóa, cùng nội dung lỗi và cùng quy ước như eSIM, và đơn đặt của chúng nằm trong cùng lịch sử tài khoản.
Tìm kiếm, định giá và đặt vé máy bay, thanh toán đơn đang giữ, hủy và đọc vé.
Tìm khách sạn, kiểm tra giá phòng, đặt trước và đặt phòng, đọc voucher và hủy.
- API đưa đón sân bayXem trước
Báo giá, đặt, theo dõi và hủy các chuyến đưa đón sân bay.
Không muốn viết mã? Đại lý cũng có thể bán eSIM ngay từ bảng điều khiển FX-Port. Bán eSIM từ bảng điều khiển
Chạy đơn eSIM đầu tiên của bạn ở sandbox
Hãy tạo tài khoản, tạo khóa sandbox, liệt kê gói, tạo đơn và đọc dung lượng đã dùng ngay hôm nay. Khóa Live sẽ có sau khi đại lý của bạn được duyệt.