1. 홈
  2. eSIM API

신규OpenAPI 3.1 파일을 함께 제공하는 REST 방식의 API 서비스

여행사와 OTA, 리셀러를 위한 eSIM API 서비스

하나의 REST API로 여행용 eSIM을 판매하세요. 여행사 통화 기준 가격으로 국가별 데이터 패키지를 조회하고, 여행객 대신 주문하고, QR 코드를 전달하고, 사용량을 확인하고 충전할 수 있습니다. 하나의 Base URL로 샌드박스와 라이브를 모두 사용합니다. 무료 샌드박스 키로 시작하세요. 라이브 키는 여행사 승인 후 사용할 수 있습니다.

무료 샌드박스 키 받기eSIM 가이드 읽기

문서는 영어로 작성되어 있습니다.

Base URL
https://api.fx-port.com/api/v1
인증
Authorization: Bearer fxp_test_...
키 접두사
fxp_test_ / fxp_live_
엔드포인트
12
패키지 제공 국가
190+
코드 샘플 언어
9

이 페이지의 목차

  • 콘솔
  • 5단계
  • 가격
  • 판매 후
  • 엔드포인트
  • 운영 환경
  • Sandbox
  • 누가 만드는가
  • FAQ
  • 관련 API
  • 시작하기

호출 단위로 보는 eSIM API

eSIM 판매 과정을 요청이 만들어지고, 전송되고, 응답을 받는 순서대로 따라가 보세요. 세션은 eSIM 판매, 여행객의 연결 유지, 기기와 예약 확인, 처리해 둘 만한 실패 사례를 다룹니다. 요청과 응답은 문서의 예시이며, 이 페이지는 API를 호출하지 않습니다.

요청 3개: 패키지 조회, eSIM 주문, 설치 데이터 조회.

예시 세션입니다. 본문은 문서의 예제이며, 날짜는 항상 오늘 이후가 되도록 조정했고, 소요 시간은 예시입니다. 이 페이지는 요청을 전송하지 않습니다.

Postman 컬렉션 다운로드

패키지 찾기, 주문, 설치 데이터 조회

한 국가의 패키지를 조회하는 것으로 시작해 여행객을 위해 하나를 주문하고, 주문의 설치 데이터를 조회합니다. 샌드박스는 가짜 활성화 코드가 든 테스트 eSIM을 만들며 차감되는 금액은 없습니다. 콘솔에는 카탈로그 응답을 줄여 놓은 사본이 표시됩니다.

  1. 패키지 조회

    카탈로그 호출은 country와 type을 받아 조건에 맞는 패키지를 여행사 통화 기준 가격으로 돌려줍니다. 여행객이 고른 패키지의 package_id를 보관하세요.

    요청 GET /esims/packages
    curl 'https://api.fx-port.com/api/v1/esims/packages?country=france&type=local' \
      -H "Authorization: Bearer fxp_test_YOUR_KEY"
    응답 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
      }
    }

    표시용으로 줄인 예시

    • PASS 상태 코드가 200입니다
    • PASS $.success가 true와 같음
    • PASS $.data[0].package_id 존재함
    • PASS $.data[0].balance_debit_amount 존재함

    문서의 GET /esims/packages 레퍼런스

  2. eSIM 주문

    주문 생성에는 package_id와 여행객의 이메일 주소, 전화번호가 필요합니다. 응답의 booking_id와 data.iccid를 보관하세요. 샌드박스에서는 balanceDebited, transactionCreated, payoutCreated가 모두 false입니다.

    요청 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"
    }'
    응답 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
    }

    표시용으로 줄인 예시

    • PASS 상태 코드가 200입니다
    • PASS $.environment가 sandbox와 같음
    • PASS $.balance_debited가 false와 같음
    • PASS $.data.iccid 존재함

    문서의 POST /esims/orders 레퍼런스

  3. 설치 데이터 조회

    설치 데이터 호출은 booking_id를 받아 주문의 QR 코드, 활성화 데이터, 설치 링크, 설치 단계를 돌려줍니다. eSIM을 소유한 여행객에게만 보여 주세요.

    요청 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"
    응답 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"
      }
    }

    표시용으로 줄인 예시

    • PASS 상태 코드가 200입니다
    • PASS $.data.package_id가 france-in-7days-1gb와 같음
    • PASS $.data.sims[0].iccid 존재함

    문서의 GET /esims/bookings/{booking_id}/setup-instructions 레퍼런스

사용량 조회 후 충전

여행객이 eSIM을 갖게 되면 남은 데이터를 조회하고, 바로 그 eSIM에 추가할 수 있는 패키지를 확인한 뒤 충전을 생성합니다. 사용량은 캐시되므로 수치가 몇 분 지난 값일 수 있습니다. 충전 내역은 사이드바와 기록에서 볼 수 있습니다.

  1. 사용량 조회

    사용량 호출은 주문의 ICCID를 받아 메가바이트 단위의 remaining과 total, status, 만료일을 돌려줍니다. 응답은 캐시에서 오며, force=true를 보내면 공급사에 다시 물어봅니다.

    요청 GET /esims/usage/{iccid}
    curl https://api.fx-port.com/api/v1/esims/usage/8900000540463077957 \
      -H "Authorization: Bearer fxp_test_YOUR_KEY"
    응답 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 상태 코드가 200입니다
    • PASS $.data.data.status가 ACTIVE와 같음
    • PASS $.data.data.remaining 존재함

    문서의 GET /esims/usage/{iccid} 레퍼런스

  2. 충전 패키지 조회

    이 호출은 오늘 바로 이 eSIM에 추가할 수 있는 패키지를 보여 줍니다. 목록이 비어 있으면 지금은 충전할 수 없는 eSIM입니다. 충전의 package_id는 최초 주문이 아니라 이 목록에서 가져오세요.

    요청 GET /esims/topup-packages/{iccid}
    curl https://api.fx-port.com/api/v1/esims/topup-packages/8900000540463077957 \
      -H "Authorization: Bearer fxp_test_YOUR_KEY"
    응답 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
          }
        ]
      }
    }

    표시용으로 줄인 예시

    • PASS 상태 코드가 200입니다
    • PASS $.data.data의 항목 수: 2개
    • PASS $.data.data[0].type가 topup와 같음

    문서의 GET /esims/topup-packages/{iccid} 레퍼런스

  3. 충전 생성

    충전 생성에는 앞의 목록에서 가져온 package_id와 ICCID가 필요합니다. 라이브에서는 공급사가 수락한 뒤에만 잔액에서 차감됩니다. 샌드박스에서는 응답의 balance가 0이며 차감되는 금액은 없습니다.

    요청 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"
    }'
    응답 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 상태 코드가 200입니다
    • PASS $.environment가 sandbox와 같음
    • PASS $.balance_debited가 false와 같음
    • PASS $.data.balance.current가 0와 같음

    문서의 POST /esims/topups 레퍼런스

  4. 충전 내역 조회

    충전 내역은 eSIM 하나의 충전을 최신순으로 보여 줍니다. 충전은 예약 목록에 없으므로 여기서 찾으면 됩니다.

    요청 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"
    응답 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 상태 코드가 200입니다
    • PASS $.data[0].type가 topup와 같음

    문서의 GET /esims/bookings/{iccid}/topup-history 레퍼런스

기기 확인 후 예약 조회

판매 전에는 여행객의 휴대폰이 eSIM을 지원하는지 확인하세요. 판매 후에는 예약을 조회하고, 예약 참조 번호가 여행사의 것인지 확인하세요. 일괄 사용량은 사이드바에 있습니다.

  1. 기기 목록 확인

    호환 기기 호출은 eSIM을 지원하는 것으로 알려진 기기를 brand, model, os와 함께 돌려줍니다. 판매하기 전에 여행객의 휴대폰을 찾아보세요.

    요청 GET /esims/compatible-devices
    curl https://api.fx-port.com/api/v1/esims/compatible-devices \
      -H "Authorization: Bearer fxp_test_YOUR_KEY"
    응답 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 상태 코드가 200입니다
    • PASS $.success가 true와 같음
    • PASS $.data[0].model 존재함

    문서의 GET /esims/compatible-devices 레퍼런스

  2. 예약 목록 조회

    예약 목록은 여행사가 주문한 eSIM을 최신순으로 돌려줍니다. 이 요청은 limit으로 예약 하나만 요청하며, pagination은 조건에 맞는 주문의 수와 다음 페이지가 있는지를 알려 줍니다.

    요청 GET /esims/bookings
    curl 'https://api.fx-port.com/api/v1/esims/bookings?limit=1' \
      -H "Authorization: Bearer fxp_test_YOUR_KEY"
    응답 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 상태 코드가 200입니다
    • PASS $.data의 항목 수: 1개
    • PASS $.pagination.has_more가 true와 같음

    문서의 GET /esims/bookings 레퍼런스

  3. 소유 확인

    소유 확인은 예약이 여행사의 것이면 is_owner를 true로 응답합니다. 다른 여행사의 예약과 존재하지 않는 예약은 같은 응답을 받으므로, 이 호출로 참조 번호를 알아낼 수는 없습니다.

    요청 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"
    응답 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 상태 코드가 200입니다
    • PASS $.is_owner가 true와 같음

    문서의 GET /esims/bookings/{booking_id}/verify 레퍼런스

  4. 사용량 일괄 조회

    한 번의 호출로 iccids에 나열한 여러 eSIM의 사용량을 읽고, ICCID별로 각자의 status가 담긴 항목 하나씩을 돌려줍니다. iccids는 항상 보내세요.

    요청 GET /esims/usage/bulk
    curl 'https://api.fx-port.com/api/v1/esims/usage/bulk?iccids=8900000540463077957' \
      -H "Authorization: Bearer fxp_test_YOUR_KEY"
    응답 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 상태 코드가 200입니다
    • PASS $.data[0].status가 success와 같음

    문서의 GET /esims/usage/bulk 레퍼런스

실패 사례와 각각의 대응 방법

모든 실패는 하나의 본문 형식을 공유하며, errors의 첫 항목에는 변하지 않는 code가 있습니다. 이 주문 호출들은 서로 다른 이유로, 서로 다른 대응이 필요하도록 일부러 실패시킨 것입니다.

  1. 주문에 읽기 키 사용

    주문 호출에 읽기 키를 쓰면 본문을 읽기도 전에 403과 read_write_permission_required로 거부됩니다. 읽기+쓰기 키로 바꾸세요.

    요청 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"
    }'
    응답 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 상태 코드가 403입니다
    • PASS 오류 코드가 read_write_permission_required입니다
    • PASS $.errors[0].type가 permission_error와 같음

    문서의 POST /esims/orders 레퍼런스

  2. 잘못된 이메일 주소

    이메일 주소가 아닌 값은 400과 invalid_email로 거부되며, field에는 email이 표시됩니다. 같은 요청은 같은 방식으로 실패하므로, 주문을 다시 보내기 전에 값을 고치세요.

    요청 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"
    }'
    응답 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 상태 코드가 400입니다
    • PASS 오류 코드가 invalid_email입니다
    • PASS $.errors[0].field가 email와 같음

    문서의 POST /esims/orders 레퍼런스

  3. 중복 주문

    이미 처리 중인 패키지에 대한 주문은 409와 duplicate_request로 거부됩니다. 곧바로 다시 보내지 말고 먼저 예약을 조회해 보고, 생성된 것이 없을 때만 다시 주문하세요.

    요청 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"
    }'
    응답 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 상태 코드가 409입니다
    • PASS 오류 코드가 duplicate_request입니다
    • PASS $.errors[0].type가 conflict와 같음

    문서의 POST /esims/orders 레퍼런스

  4. 요청 과다

    분당 한도를 넘으면 호출이 429와 rate_limit_exceeded로 거부되며, Retry-After 헤더가 기다려야 할 초를 알려 줍니다. 그다음 백오프를 적용해 재시도하세요.

    요청 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"
    }'
    응답 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 상태 코드가 429입니다
    • PASS 오류 코드가 rate_limit_exceeded입니다
    • PASS 헤더 Retry-After 있음
    • PASS $.errors[0].details.retry_after가 12와 같음

    문서의 POST /esims/orders 레퍼런스

카탈로그에서 연결된 여행객까지, 5단계

연동은 짧은 흐름입니다. 카탈로그를 조회하고, 주문을 만들고, 여행객에게 eSIM을 전달하고, 사용량을 확인하고, 데이터가 떨어지면 충전합니다. 데이터를 변경하는 것은 주문과 충전뿐이고, 나머지 호출은 모두 조회만 합니다.

한 목적지의 카탈로그 조회

한 국가의 패키지를 여행사 통화 기준 가격으로 조회하고, 여행객이 고른 패키지의 package_id를 보관하세요. country는 항상 보내세요. 전체 카탈로그는 페이지 나누기 없이 매우 큰 응답으로 돌아옵니다. 카탈로그는 바뀔 수 있으므로 패키지 ID는 코드에 고정하지 말고 응답에서 읽으세요.

  • GET /api/v1/esims/packages

요청

curl 'https://api.fx-port.com/api/v1/esims/packages?country=france&type=local' \
  -H "Authorization: Bearer fxp_test_YOUR_KEY"

응답 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
  }
}

국가별 패키지 카탈로그

주문 생성

package_id와 여행객의 이메일 주소, 전화번호를 보내세요. 주문 하나는 정확히 eSIM 하나를 만들며, 라이브에서는 여행사 잔액에서 차감됩니다. 이후 모든 호출에 둘 중 하나가 필요하므로 응답의 booking_id와 ICCID를 보관하세요.

  • POST /api/v1/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"
}'

응답 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
}
주문 응답에 들어 있는 항목
필드담고 있는 내용
booking_id 주문의 FX-Port 참조 번호입니다. 설치 데이터, 소유 확인, 자체 기록에 사용하도록 보관하세요.
data.iccid eSIM의 식별자입니다. 사용량, 충전, 설치 안내는 모두 ICCID로 요청합니다.
data.sim.qrcode data.sim.qrcode_url QR 코드에 담긴 활성화 문자열과 QR 코드 이미지 링크입니다.
data.sim.direct_apple_installation_url data.sim.sharing iPhone에서 설치를 시작하는 링크와, 여행객이 액세스 코드로 eSIM을 열 수 있는 공유 페이지입니다. Android용 링크는 설치 데이터 호출에서 추가로 제공됩니다.
활성화 데이터는 민감한 정보입니다. eSIM을 소유한 여행객에게만 보여 주세요.
공급사가 아직 eSIM을 돌려주지 않았더라도 주문은 생성되어 있습니다. 이때 ICCID는 PENDING-으로 시작하며, 공급사에서 데이터를 받으면 설치 데이터 호출에서 확인할 수 있습니다.

eSIM 주문 생성

여행객에게 eSIM 전달

응답에 QR 코드와 활성화 문자열이 들어 있어 자체 화면에 바로 표시할 수 있습니다. FX-Port는 공급사가 여행객의 이메일 주소로 QR 코드와 공유 링크를 보내도록 요청하므로, 직접 전달하지 않아도 됩니다. 설치 데이터 호출은 나중에도 같은 데이터를 설치 단계와 함께 다시 돌려줍니다.

  • GET /api/v1/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"

응답 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
  }
}

예약 또는 ICCID별 설치 데이터

사용량 확인

ICCID로 eSIM의 남은 데이터와 만료일을 조회합니다. 응답은 최대 15분 동안 캐시되므로, 계량기가 아니라 화면 표시나 알림용으로 사용하세요.

  • GET /api/v1/esims/usage/{iccid}

요청

curl https://api.fx-port.com/api/v1/esims/usage/8900000540463077957 \
  -H "Authorization: Bearer fxp_test_YOUR_KEY"

응답 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"
    }
  }
}

eSIM 사용량 단건·일괄 조회

데이터가 떨어지면 충전

바로 이 eSIM에 추가할 수 있는 패키지를 조회한 뒤, 그중 하나로 충전을 생성하세요. 목록이 비어 있으면 지금은 충전할 수 없는 eSIM이므로, 여행객에게 새 eSIM이 필요합니다.

  • GET /api/v1/esims/topup-packages/{iccid}
  • POST /api/v1/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"
}'

응답 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
}

충전 확인 및 생성

가격, 커미션, 잔액

모든 패키지에는 서버에서 여행사 통화로 계산한 금액 필드가 들어 있습니다. 요청 본문에 보낸 가격은 무시되므로, 주문은 항상 서버가 계산한 가격으로 생성됩니다.

eSIM 패키지의 금액 필드
필드담고 있는 내용
base_price price 여행사 커미션을 더하기 전의 패키지 가격입니다. 잔액에서 차감되는 금액이 아닙니다.
total_price retail_price 커미션이 포함된, 여행객에게 청구할 가격입니다.
balance_debit_amount b2b_price 라이브에서 패키지를 주문할 때 여행사 잔액에서 빠져나가는 금액입니다. 계산하지 말고 읽어 오세요.
agency_commission commission_rate 여행사의 커미션율이며 텍스트와 숫자로 제공됩니다. 예약 응답에서는 커미션이 금액으로 돌아옵니다.

카탈로그 예시에서 여행객은 468.84 DZD를 지불합니다. 라이브 주문은 잔액에서 418.60 DZD를 차감하며, 그 차액인 50.24 DZD가 여행사 커미션입니다.

요율은 여행사마다 다릅니다

커미션율은 모든 패키지와 함께 반환되며 여행사마다 다릅니다. 계약을 맺은 기업 여행사는 요율이 0일 수 있고, 이 경우 총 가격이 차감액과 같습니다.

필드는 계산하지 말고 읽으세요

차감액에는 여행사별 금액이 포함되므로 기본 가격보다 높을 수 있습니다. 따라서 balance_debit_amount를 읽고, base_price로 직접 계산하지 마세요. price라는 단어는 카탈로그에서는 기본 가격이지만 주문, 충전 패키지, 설치 데이터에서는 판매 가격을 뜻합니다. 모든 곳에서 base_price와 total_price를 사용하면 이 모호함이 사라집니다.

여행사 통화로 표시된 가격

공급사가 어떤 통화를 쓰든 모든 금액은 이미 여행사 통화로 환산되어 있습니다. 응답에는 공급사 통화와 환율도 함께 표시되므로 환율을 직접 검증할 수 있고, 다시 환산할 필요가 없습니다.

eSIM 가격 구성 방식

판매 후 처리: 사용량, 충전, 설치 데이터

판매는 주문으로 끝나지 않습니다. 다음 호출은 여행객의 연결을 유지해 주며, 키와 같은 환경에서 여행사가 주문한 eSIM에만 작동합니다.

사용량 조회와 수치가 얼마나 최신인지

사용량 호출은 eSIM 하나, 또는 한 번에 최대 50개 eSIM의 남은 데이터, 제공량, 상태, 만료일을 돌려줍니다. FX-Port는 공급사의 요청 한도를 보호하기 위해 마지막 응답을 최대 15분 동안 보관하므로, 수치가 그만큼 오래된 것일 수 있습니다. 충전 직후처럼 공급사에 다시 물어야 할 때는 force=true를 보내세요. 공급사가 사용량 조회 횟수를 제한하므로 모든 요청에 쓰지는 마세요. 공급사가 응답하지 못하면 마지막으로 알려진 수치가 오래된 값으로 표시되어 돌아옵니다.

eSIM 사용량 단건·일괄 조회

충전: 먼저 조회하고, 그다음 생성

충전은 두 번의 호출로 이루어집니다. 먼저 바로 이 eSIM에 추가할 수 있는 패키지를 조회하고, 돌아온 패키지 ID 중 하나로 충전을 생성하세요. 최초 주문의 패키지 ID를 재사용하지 말고, 충전 패키지를 나중을 위해 보관하지도 마세요. 여행객이 충전하려 할 때 다시 조회하세요. 충전은 eSIM에 데이터를 추가할 뿐 남은 데이터를 대체하지 않으므로, 결과는 force=true로 사용량을 조회해 확인하세요.

충전 확인 및 생성

충전할 수 없는 경우

공급사는 국가별로 서비스할 이동통신사를 정하며, 드물게 이를 바꾸기도 합니다. 그러면 eSIM은 만료될 때까지 계속 작동하지만 해당 패키지는 더 이상 충전할 수 없습니다. 충전 패키지 목록은 빈 상태로 돌아옵니다. 공급사가 충전을 거부해도 잔액은 변하지 않으며, 시도 내역은 실패한 예약으로 저장됩니다. 응답은 대응할 수 있는 supplier_error입니다.

충전이 불가능할 수 있는 이유

설치 데이터와 설치 단계

설치 데이터 호출은 주문의 QR 코드, 활성화 데이터, 설치 링크, 설치 단계를 필요할 때마다 돌려줍니다. 안내 호출은 요청한 언어로 운영체제별 단계를 돌려줍니다. 이 단계는 공급사가 제공하는 일반 텍스트이므로 주문의 QR 코드와 함께 표시하세요. 둘 다 eSIM을 소유한 여행객에게만 보여 주세요.

예약 또는 ICCID별 설치 데이터

예약, 충전 내역, 소유 확인

예약 목록은 키의 환경에서 여행사가 주문한 eSIM을 최신순으로 돌려줍니다. 예약 ID, 여행객 이름, 이메일 주소, 패키지 이름, ICCID로 검색할 수 있습니다. 충전은 이 목록에 없으며, eSIM의 충전 내역으로 조회하세요. 예약 ID로 링크나 화면을 만들기 전에 소유 확인으로 본인 여행사의 예약인지 알 수 있습니다. 다른 여행사의 예약과 존재하지 않는 예약은 같은 응답을 받습니다.

eSIM 예약 조회 및 확인

모든 eSIM 엔드포인트와 OpenAPI 파일, Postman 컬렉션, 코드 샘플 안내

eSIM API는 하나의 Base URL 아래에 12개의 엔드포인트가 있습니다. 각 행을 누르면 해당 호출의 레퍼런스 페이지가 열리며, 요청 필드, 응답, 오류, 9개 언어의 예시를 볼 수 있습니다.

메서드, 경로, 키 권한, 용도를 정리한 eSIM API 엔드포인트
엔드포인트기능키
GET /api/v1/esims/packages한 국가 또는 지역의 패키지를 여행사 통화 기준 가격으로 조회합니다. 국가는 항상 보내세요. 전체 카탈로그는 매우 크고 페이지 나누기가 없습니다.읽기
GET /api/v1/esims/compatible-devices여행객이 구매하기 전에 확인할 수 있도록, eSIM을 지원하는 것으로 알려진 기기 목록입니다.읽기
POST /api/v1/esims/orders여행객을 위해 패키지에서 eSIM 하나를 생성하고 공급사에 프로비저닝합니다. 라이브에서는 여행사 잔액에서 차감됩니다.읽기+쓰기
GET /api/v1/esims/topup-packages/{iccid}지금 바로 이 eSIM에 추가할 수 있는 패키지입니다. 목록이 비어 있으면 지금은 충전할 수 없습니다.읽기
POST /api/v1/esims/topups기존 eSIM에 충전 패키지를 추가합니다. 라이브에서는 공급사가 수락한 뒤에만 잔액에서 차감됩니다.읽기+쓰기
GET /api/v1/esims/usage/{iccid}eSIM 하나의 남은 데이터, 제공량, 상태, 만료일입니다. 응답은 최대 15분 지난 값일 수 있습니다.읽기
GET /api/v1/esims/usage/bulk한 번의 호출로 최대 50개 eSIM의 사용량을 ICCID별 항목과 각자의 상태로 조회합니다.읽기
GET /api/v1/esims/bookings여행사가 주문한 eSIM을 최신순으로 검색과 페이지 나누기와 함께 조회합니다. 충전은 이 목록에 없습니다.읽기
GET /api/v1/esims/bookings/{iccid}/topup-historyeSIM 하나의 충전 내역을 최신순으로 조회합니다. 충전이 없으면 목록이 비어 있습니다.읽기
GET /api/v1/esims/bookings/{booking_id}/verify링크나 화면을 만들기 전에 예약 참조 번호가 여행사의 것인지 확인합니다.읽기
GET /api/v1/esims/bookings/{booking_id}/setup-instructions주문의 QR 코드, 활성화 데이터, 설치 링크, 설치 단계를 JSON으로 돌려줍니다.읽기
GET /api/v1/esims/instructions/{iccid}ICCID 하나에 대한 단계별 설치 안내를 운영체제별로, 요청한 언어로 돌려줍니다.읽기

OpenAPI 3.1

파일 하나가 모든 엔드포인트와 필드를 설명합니다. 이 파일로 클라이언트를 생성하거나, API 도구로 가져오거나, 코딩 어시스턴트에 전달하세요.

OpenAPI 3.1 파일

Postman 컬렉션

eSIM 컬렉션은 판매 단계에 맞춘 폴더로 12개 엔드포인트를 모두 담고 있습니다. 키는 들어 있지 않으니 직접 추가하세요.

eSIM 판매 요청 예제를 담은 Postman 컬렉션

9개 언어로 된 코드 샘플

모든 레퍼런스 페이지는 OpenAPI 설명에서 생성한 요청 예시를 cURL, Node.js, Python, PHP, Go, Java, C#, Swift, Kotlin으로 보여 줍니다. 어떤 eSIM 요청이든 이 언어들로 모두 확인할 수 있습니다.

전체 API 레퍼런스

AI 어시스턴트용 문서

llms.txt와 llms-full.txt는 AI 어시스턴트에 문서를 일반 텍스트로 제공하며, 모든 문서 페이지는 주소 끝에 .md를 붙이면 Markdown으로 읽을 수 있습니다.

AI 도구를 위한 llms.txt 색인 파일

eSIM API 개요와 사용 문서

운영 환경을 위한 설계: 키, 오류, 재시도, 캐시

eSIM 연동은 운영 환경에서 인증, 실패 처리, 재시도, 캐시, 요청 한도로 평가받습니다. 각각에 대해 알아 둘 내용입니다.

하나의 Base URL, 두 종류의 키

모든 요청은 Authorization 헤더에 Bearer 토큰으로 키를 담아 보냅니다. 접두사가 키를 쓸 수 있는 환경을 알려 줍니다. 샌드박스는 fxp_test_, 라이브는 fxp_live_입니다. 둘 다 같은 Base URL을 사용하며, 모든 JSON 응답은 environment에 응답이 나온 환경을 표시합니다. 키는 브라우저나 앱이 아니라 서버에 보관하세요. FX-Port는 키의 해시만 보관하므로 분실한 키는 다시 보여 드릴 수 없습니다. 키 변경이 적용되기까지 몇 분 걸릴 수 있습니다.

사용 환경과 Postman 컬렉션 안내

어떤 키로 어떤 호출을 하는가

읽기 키로는 패키지 조회, 기기 확인, 사용량 조회, 예약 조회를 할 수 있습니다. 주문이나 충전을 생성하려면 읽기+쓰기 키가 필요하며, 읽기 키로 시도하면 read_write_permission_required가 돌아옵니다. 모든 키는 IP 주소 목록으로 제한할 수 있고, 다른 주소에서 호출하면 ip_not_allowed가 돌아옵니다. 코드가 결과만 보여 주는 곳에는 읽기 키를 사용하세요.

키와 권한 수준

모든 실패에 하나의 오류 형식

호출이 실패하면 errors 배열이 돌아옵니다. 첫 항목에는 변하지 않는 code, 대응 방법을 알려 주는 type, 문제가 된 field가 들어 있습니다. 메시지가 아니라 코드를 기준으로 판단하세요. 항공권, 호텔, eSIM, 계정이 함께 쓰는 오류 목록에는 180개의 코드가 있습니다. 공급사가 주문이나 충전을 거부하면 공급사의 HTTP 상태를 담은 supplier_error가 돌아옵니다. 이때 차감되는 금액은 없으며 실패한 예약이 저장됩니다. 재시작 직후에는 카탈로그와 기기 목록이 success가 false인 202로 응답할 수 있습니다. 몇 초 기다린 뒤 다시 요청하세요.

전체 오류 코드 목록

이중 주문 없이 재시도하기

FX-Port에는 멱등성 키가 없으므로 보낼 Idempotency-Key 헤더도 없습니다. 조회는 반복해도 안전하지만, 주문이나 충전 생성은 그렇지 않습니다. FX-Port는 명백한 중복을 409와 duplicate_request로 거부합니다. 아직 처리 중인 패키지에 대한 주문이 그 예입니다. 라이브에서는 여행객이 누구든, 여행사의 가장 최근 확정 주문으로부터 60초 이내에 같은 패키지를 다시 주문하는 것도 거부합니다. 주문은 보통 몇 초 안에 응답하지만 공급사가 느리면 훨씬 오래 걸릴 수 있습니다. 호출이 시간 초과되거나 연결이 끊겼다면 곧바로 주문을 다시 보내지 마세요. eSIM이 이미 만들어졌을 수 있습니다. 예약 목록의 search 파라미터에 여행객의 이메일 주소를 넣어 찾아보고, 아무것도 생성되지 않았을 때만 다시 주문하세요.

시간 초과 후 안전하게 재시도하기

웹훅 없음: 필요할 때 직접 조회

FX-Port는 샌드박스에서도 라이브에서도 사용자의 URL을 호출하지 않습니다. 주문은 eSIM과 함께, 또는 공급사가 아직 eSIM을 돌려주지 않았다면 PENDING- 자리표시자와 함께 응답합니다. 그 밖의 정보는 필요할 때 직접 요청하세요. 설치 데이터, 사용량, 예약 목록이 그렇습니다.

캐시와 속도

사용량은 최대 15분, 충전 패키지 목록은 몇 분 동안 보관되며, force=true를 보내면 캐시를 건너뜁니다. 필터 없는 카탈로그는 페이지 나누기 없는 매우 큰 응답이므로 country를 보내고 Accept-Encoding: gzip으로 압축을 허용하세요. 패키지 제목은 locale 파라미터의 언어로 돌아옵니다. 영어가 아닌 언어로 처음 요청하면 텍스트를 그때 가져와 이후에 캐시하므로 더 느립니다.

요청 한도

한도는 키별, 분당으로 두 그룹에 나뉘어 집계되며, 모든 응답에 ratelimit-limit과 ratelimit-remaining이 들어 있어 거부되기 전에 속도를 늦출 수 있습니다. 429를 받으면 Retry-After에 적힌 초만큼 기다린 뒤 지수 백오프와 지터로 재시도하세요. 하나의 키나 에이전시에서 주문이나 충전이 동시에 너무 많이 진행되면 concurrency_limit_exceeded가 응답될 수 있습니다.

키별 eSIM 요청 한도
호출 종류분당
주문 및 충전 생성1,200
그 밖의 모든 eSIM 엔드포인트6,000

현재 주문과 충전의 동시 처리 상한은 관찰 모드입니다. 집계는 하지만 적용하지는 않으므로 아직 이 때문에 거부되는 요청은 없으며, 적용 시작일은 변경 내역에서 공지합니다. 이 수치는 약속이 아니라 현재 정책으로 보세요. 샌드박스 키도 라이브 키와 분당 카운터가 같으므로, 부하 테스트는 반복문으로 돌리지 말고 일정을 잡아 진행하세요.

키별 요청 한도

이름과 버전

요청 필드는 first_name, agent_id처럼 snake_case입니다. 이전 표기도 여전히 작동합니다. user_id는 agent_id로 읽히며 warnings 항목이 추가되고, customer_email은 경고 없이 email로 받아들여집니다. 많은 응답은 code 옆의 order_id처럼 이전 키를 같은 값의 snake_case 키와 나란히 유지하며, ?naming=snake를 붙이면 snake_case 키만 돌아옵니다. 버전은 경로의 /api/v1에 있습니다. 호환되지 않는 변경은 새 접두사로 나오고, 새 필드와 표기는 기존 것에 더해지는 방식으로 추가됩니다.

무료 샌드박스에서 시작하고, 이후 라이브로

이 페이지의 모든 내용은 오늘 샌드박스에서 작동합니다. 샌드박스 키는 직접 만들 수 있고 무료이며, 실제 잔액에는 영향을 주지 않습니다.

  1. 1

    계정 만들기

    FX-Port 계정에 가입하세요. 샌드박스 키는 무료이며, 샌드박스 예약에는 실제 요금이 청구되지 않습니다.

    FX-Port 계정에 가입하기

  2. 2

    샌드박스 키 만들기

    대시보드의 API 페이지에서 fxp_test_로 시작하는 키를 만드세요. 읽기 키는 검색과 조회를 할 수 있고, 읽기+쓰기 키는 테스트 예약도 만들 수 있습니다.

    대시보드의 API 페이지 열기

  3. 3

    첫 요청 보내기

    Base URL은 하나이며, 키는 Bearer 토큰으로 Authorization 헤더에 넣습니다. 퀵스타트에서 첫 호출 과정을 안내합니다.

    API 퀵스타트 읽기

  4. 4

    준비되면 라이브로 전환

    fxp_live_ 키로 교체하세요. 라이브는 여행사 승인 후 사용할 수 있으며, 그 전에는 API가 403 agency_not_active로 응답합니다. 실제 예약은 충전된 잔액에서 결제됩니다.

    라이브 전환 방법 읽기

cURL로 보내는 첫 카탈로그 요청입니다. 문서에는 지원하는 모든 언어로 같은 요청이 나와 있습니다.

요청

curl 'https://api.fx-port.com/api/v1/esims/packages?country=france&type=local' \
  -H "Authorization: Bearer fxp_test_YOUR_KEY"

빠른 시작: 첫 샌드박스 호출

샌드박스가 하는 일

샌드박스에서 주문하면 공급사에 실제 테스트 eSIM이 만들어지지만 활성화 코드가 가짜여서 휴대폰에는 설치할 수 없습니다. 차감되는 금액은 없으며 응답에도 balanceDebited, transactionCreated, payoutCreated가 모두 false로 표시됩니다. 충전 응답의 잔액은 0입니다. 사용량은 고정되어 있어 새 eSIM은 제공량 전체와 ACTIVE 상태로 표시됩니다. 샌드박스 예약은 샌드박스 키에서만 보입니다.

샌드박스의 eSIM

라이브에서만 테스트할 수 있는 것

잔액 확인, 중복 확인, 잔액 잠금은 라이브에서만 실행됩니다. 그래서 402와 insufficient_balance, 같은 패키지를 60초 이내에 다시 주문했을 때의 409, 503과 balance_lock_timeout 응답은 샌드박스에 나타나지 않습니다. 이 오류들의 처리는 오류 코드 목록을 보고 작성하세요.

전체 오류 코드 목록

라이브로 전환

라이브 키는 여행사 승인에 묶여 있습니다. 여행사가 승인되기 전에는 라이브 키가 agency_not_active로 응답하고 샌드박스 키는 계속 작동합니다. 라이브 주문은 충전된 여행사 잔액에서 결제됩니다. 샌드박스와 라이브가 하나의 Base URL을 공유하므로, 라이브 전환은 코드가 아니라 키만 바꾸는 일입니다.

라이브 키에 필요한 승인

eSIM API로 서비스를 만드는 사람들

같은 호출이라도 고객 유형마다 중요하게 쓰는 부분이 다릅니다.

여행 상품을 파는 여행사

여행사는 항공권과 호텔 옆에서 eSIM을 판매합니다. 여행객 본인의 이메일 주소로 주문하면 공급사가 QR 코드와 공유 링크를 보내 주고, 여행객이 문의하면 사용량을 조회합니다. 커미션율은 패키지마다 함께 돌아오며, agent_id는 여행사의 어느 사용자가 주문했는지 기록합니다.

OTA와 마켓플레이스

마켓플레이스는 탐색 페이지부터 만듭니다. 한 번에 한 국가씩, 국가 단위 또는 지역 단위 패키지, 패키지별 통신망과 데이터 제공량을 보여 주고, 여행객이 구매하기 전에 기기를 확인합니다. 여행객의 eSIM을 나열하는 화면은 한 번의 호출로 최대 50개의 사용량을 읽을 수 있습니다.

여행 기술 기업과 기업 출장 팀

여행 기술 기업과 기업 출장 부서는 자체 예약 도구를 만듭니다. 시작에 필요한 것은 모두 공개되어 있습니다. OpenAPI 파일, Postman 컬렉션, AI 코딩 어시스턴트가 읽을 수 있는 일반 텍스트 문서가 있어, 첫 프로토타입을 실제 계약에서 출발할 수 있습니다.

eSIM API에 대해 자주 묻는 질문

FX-Port eSIM API는 무엇이고, 누구를 위한 것인가요?

여행사, OTA, 리셀러가 하나의 연동으로 여행용 데이터 eSIM을 판매할 수 있게 해 주는 REST API입니다. 여행사 통화 기준 가격으로 목적지의 패키지를 조회하고, 여행객을 위해 하나를 주문합니다. 여행객에게 QR 코드를 전달하고, 사용량을 확인하고, 충전할 수 있습니다. 모든 통신은 HTTPS 위의 JSON이며, OpenAPI 파일이 모든 엔드포인트를 설명합니다.

무료 샌드박스가 있나요? 키는 어떻게 받나요?

네. FX-Port 계정을 만들고 대시보드의 API 페이지에서 샌드박스 키를 만드세요. 직접, 무료로 만들 수 있습니다. 샌드박스에서 주문하면 가짜 활성화 코드가 든 테스트 eSIM이 만들어지므로 휴대폰에는 설치할 수 없습니다. 잔액에서 차감되는 금액은 없습니다. 샌드박스와 라이브가 하나의 Base URL을 공유하므로, 테스트한 코드가 그대로 운영에 쓰입니다.

라이브로 전환하려면 무엇이 필요한가요?

라이브 키가 작동하려면 여행사가 승인되어야 합니다. 그때까지 라이브 키는 거부되고 샌드박스 키는 계속 작동합니다. 라이브 주문은 충전된 여행사 잔액에서 결제되며 샌드박스는 잔액을 건드리지 않습니다. 모든 키는 IP 주소 목록으로 제한할 수 있습니다. 전환은 키만 바꾸면 되고, 모든 응답에는 응답이 나온 환경이 표시됩니다.

어떤 국가와 패키지를 판매할 수 있나요?

190개국 이상에서 패키지를 제공하며, 지역 번들은 해당 지역 아래에 표시됩니다. 패키지마다 데이터 제공량, 유효 기간, 통신망, 충전 가능 여부가 다릅니다. 이 필드와 패키지 ID는 코드에 고정하지 말고 카탈로그 응답에서 읽으세요. 전체 카탈로그는 매우 큰 응답이므로 한 번에 한 국가씩 요청하세요. 별도의 기기 목록으로 판매 전에 여행객의 휴대폰을 확인할 수 있습니다.

여행객은 eSIM을 어떻게 받나요?

주문 응답에 QR 코드, 활성화 문자열, iPhone용 설치 링크, 공유 페이지가 들어 있어 자체 화면에 표시할 수 있습니다. 또한 FX-Port는 eSIM이 생성되는 즉시 공급사가 여행객의 이메일 주소로 QR 코드와 공유 링크를 보내도록 요청합니다. 공급사가 아직 eSIM을 돌려주지 않았더라도 주문은 존재하며, 데이터는 나중에 설치 데이터 호출에서 받을 수 있습니다.

가격, 커미션, 잔액은 어떻게 연결되나요?

모든 패키지에는 여행사 통화 기준의 금액 필드가 들어 있습니다. 커미션을 더하기 전의 기본 가격, 여행객에게 청구할 총 가격, 잔액에서 차감되는 금액, 커미션율입니다. 여행사 커미션은 총 가격에서 차감액을 뺀 금액입니다. 차감액은 여행사마다 다르므로 직접 계산하지 말고 이 필드를 읽으세요. 샌드박스에서는 차감되는 금액이 없고, 라이브에서는 차감액이 여행사 잔액에서 빠져나갑니다.

eSIM을 충전할 수 있나요? 남은 데이터는 어떻게 보나요?

네, 두 번의 호출로 가능합니다. 해당 eSIM에 추가할 수 있는 패키지를 조회하고, 그중 하나로 충전을 생성하세요. 공급사가 국가의 통신사를 바꿀 수 있어 충전이 항상 가능하지는 않습니다. 이때 목록이 비어 있으면 여행객에게 새 eSIM이 필요하다는 뜻입니다. 사용량은 최대 15분 동안 캐시되므로 최근 수치로 간주하세요. 한 번의 호출로 최대 50개의 eSIM을 조회할 수 있습니다.

실패는 어떻게 알려 주나요? 웹훅이 있나요?

실패는 변하지 않는 오류 코드가 담긴 하나의 형식으로 돌아오며, 프로그램이 판단할 기준은 메시지 문구가 아니라 이 코드입니다. 조회는 백오프를 적용해 반복해도 안전합니다. 주문이나 충전 생성은 다릅니다. 멱등성 키가 없으므로 시간 초과 후에는 다시 시도하기 전에 예약을 조회하세요. FX-Port는 라이브에서 같은 패키지를 60초 이내에 두 번 주문하는 것처럼 명백한 중복을 거부합니다. 웹훅은 없습니다.

API로 eSIM 주문을 취소하거나 환불할 수 있나요?

아니요. eSIM 주문을 취소하거나 환불하는 엔드포인트는 API에 없습니다. 주문 하나는 정확히 eSIM 하나를 만들므로, 보내기 전에 패키지와 여행객의 정보를 확인하세요. 공급사가 주문을 거부하면 차감되는 금액은 없고 실패한 예약이 저장됩니다. 특정 주문에 문제가 있으면 개발팀에 문의할 때 해당 예약 ID를 함께 알려 주세요.

시작하려면 무엇이 필요하고, 어떤 도구가 도움이 되나요?

샌드박스 키와 HTTP 클라이언트가 필요합니다. 문서에는 OpenAPI 3.1 파일, Postman 컬렉션, 9개 언어의 코드 샘플, AI 어시스턴트용 일반 텍스트 문서가 추가로 제공됩니다. 키는 브라우저나 앱이 아니라 서버에 보관하세요. 더 오래 걸리는 부분은 자체 결제 화면, 여행객에게 QR 코드를 전달하는 일, 오류 처리입니다.

FX-Port에서 제공하는 다른 API 서비스

eSIM은 대개 여행과 함께 판매됩니다. 항공권과 호텔도 eSIM과 같은 키, 같은 오류 본문, 같은 규칙을 사용하며, 그 예약은 같은 계정의 내역에 쌓입니다.

  • 항공권 API

    항공권을 검색하고 가격을 확인해 예약하며, 보류된 주문을 결제하고 취소하고 티켓을 조회합니다.

  • 호텔 API

    호텔을 찾고 요금을 확인하며, 사전 예약과 예약을 하고 바우처를 조회하고 취소합니다.

  • 공항 픽업 API프리뷰

    공항 픽업의 견적, 예약, 진행 확인, 취소를 처리합니다.

코드를 작성하고 싶지 않으신가요? 여행사는 FX-Port 대시보드에서도 eSIM을 판매할 수 있습니다. 대시보드에서 eSIM 판매하기

샌드박스에서 첫 eSIM 주문 실행하기

계정을 만들고, 샌드박스 키를 발급하고, 패키지를 조회하고, 주문을 생성하고, 사용량을 읽는 일을 오늘 바로 해 볼 수 있습니다. 라이브 키는 여행사 승인 후에 사용할 수 있습니다.

계정 만들기개발팀에 이메일 보내기

이 API에 대해 AI 어시스턴트에게 물어보기

이 페이지를 어시스턴트에서 열고 단계별 연동 계획을 요청하세요.

FX-PORT

신뢰할 수 있는 B2B 여행 배포 플랫폼. 글로벌 재고에 접근하고 더 나은 요금과 쉬운 도구로 사업을 성장시키세요.

  • 약관
  • 개인정보 보호정책
  • 문의하기
  • 기업
  • 블로그
  • B2B 항공편 API
  • B2B 교통편 API
  • B2B 페리 API
  • B2B 호텔 API
  • B2B eSIM API
  • B2B 베드뱅크
  • B2B 항공편 통합업체
  • 항공사
  • 공항
  • 국가
  • eSIM

항공 서비스

FX-Port는 전 세계 항공편을 판매할 수 있는 포괄적인 B2B 항공편 배포 플랫폼입니다. 500개 이상의 항공사와 연결되어 있어 경쟁력 있는 도매 요금과 즉시 확인, 자동 티켓팅을 제공합니다.

플랫폼은 실시간 가용성, 가격 비교 도구, 자동화된 예약 관리를 제공합니다. 여행사는 독점 B2B 항공요금에 접근하고, 커미션을 관리하며, 통합 시스템을 통해 항공 운영을 간소화할 수 있습니다.

숙박 서비스

전 세계 150만 개 이상의 숙소에 접근할 수 있는 B2B 호텔 예약 플랫폼을 통해 경쟁력 있는 요금과 보장된 마진, 즉시 객실 확인을 제공합니다. 모든 숙박 카테고리에서 포괄적인 숙소 정보, 동적 가격 책정, 자동화된 예약 관리를 제공합니다.

고급 리조트부터 저렴한 옵션까지, 플랫폼은 원활한 호텔 배포를 위한 숙소 정보, 동적 가격 책정, 자동화된 예약 관리를 제공합니다.

여행 솔루션

검증된 제공업체와의 글로벌 네트워크를 통해 공항 픽업, 시티 투어, 전문 샤퍼 서비스를 포함한 포괄적인 이동 서비스를 제공합니다. 페리 예약 시스템은 주요 해상 노선을 즉시 예약할 수 있는 기능과 경쟁력 있는 B2B 요금을 제공합니다.

비자 발급, 숙박, 교통을 포함한 전문 움라 패키지를 제공합니다. 여행사를 위한 동적 가격 책정 및 자동화된 재고 관리가 포함된 맞춤형 여행 패키지.

FX-Port는 첨단 기술과 포괄적인 솔루션으로 B2B 여행 배포를 혁신합니다. 플랫폼은 여행사가 글로벌 재고에 접근하고, 경쟁력 있는 요금과 자동화된 도구로 예약을 효율적으로 관리하며 사업을 성장시킬 수 있게 합니다.

다양한 통화 지원, 현지 결제 처리, 24/7 고객 서비스를 통해 전 세계 여행사의 원활한 운영을 보장합니다. 플랫폼은 실시간 가용성, 즉시 확인, 포괄적인 예약 관리 도구를 제공합니다.

여행사는 플랫폼을 통해 항공편 예약, 호텔 예약, 이동 서비스, 페리 티켓, 움라 패키지, 맞춤형 여행 경험을 포함한 다양한 여행 서비스를 제공할 수 있습니다. B2B 마켓플레이스는 여행사를 전 세계 검증된 공급업체와 연결합니다.

FX-Port는 기업급 보안, 자동화된 커미션 관리, 상세한 분석을 통해 사업 성장을 지원합니다. 수백 개의 성공적인 여행사가 플랫폼을 사용하여 운영을 간소화하고 시장 점유율을 확대하고 있습니다.

© 2026 FX-PORT. 모든 권리 보유.

본문으로 건너뛰기
공급업체를 위한 FX-Port항공—항공사·콘솔리데이터·OTA·GDS 대리점호텔—베드뱅크·PMS/CMS·호텔모든 여행 공급업체
기업API
로그인
지금 액세스 받기
대시보드