개발자

MG Ship API로 개발하기

간단하고 버전 관리되는 REST API로 실시간 배송 가시성 데이터를 여러분의 시스템에 직접 가져오세요.

개요

MG Ship API는 HTTPS를 통해 JSON을 반환하는 REST API입니다. 이를 통해 여러분의 시스템은 배송 가시성 데이터(목록, 전체 배송 레코드, 추적 타임라인)에 프로그래밍 방식으로 접근할 수 있으며, 마일스톤을 자체 TMS, ERP 또는 고객 포털로 가져올 수 있습니다.

모든 엔드포인트는 아래의 버전이 지정된 기본 경로 아래에 위치합니다. API는 URL 경로(v1)에서 버전이 관리됩니다. 호환성을 깨뜨리는 변경 사항은 새 경로(v2)로 제공되며, 이전 버전에는 12개월의 지원 중단 기간이 적용되므로 v1을 기준으로 구축한 통합은 계속 작동합니다.

기본 URL

연동하려는 환경에 맞는 기본 URL을 선택하세요. 아래의 모든 엔드포인트 경로는 이 기본 URL을 기준으로 한 상대 경로입니다. 스테이징과 테스트(VPS)는 개발 및 테스트용이며, 프로덕션은 실제 키로만 사용하세요.

환경기본 URL
프로덕션https://api.mglobalship.com/api/v1/external
스테이징https://api.staging.mglobalship.com/api/v1/external
테스트(VPS)https://mgs.aipipis.com/api/v1/external

인증

모든 요청은 Authorization 헤더에 Bearer 토큰으로 전송되는 API 키로 인증하세요. 키는 API Portal에서 테넌트별로 발급되고 생성 시 한 번만 표시되며, 명시적인 범위(예: shipments.read)를 가지고 언제든지 교체하거나 취소할 수 있습니다.

키는 서버 측에 보관하세요. 브라우저나 모바일 코드에 절대 포함하지 마세요. 키가 노출된 경우 API Portal에서 교체하면 이전 키는 즉시 작동을 멈춥니다.

bash
curl https://api.staging.mglobalship.com/api/v1/external/health \
  -H "Authorization: Bearer mgs_live_xxxxxxxxxxxxxxxxxxxxxxxx"

규칙

페이지네이션

목록 엔드포인트는 커서 기반 페이지네이션을 사용합니다. limit(1–100, 기본값 20)을 전달하여 페이지 크기를 지정하세요. 더 많은 결과가 존재하면 응답은 has_more를 true로 설정하고 next_cursor를 반환합니다. 이를 cursor 쿼리 매개변수로 다시 전달하여 다음 페이지를 가져오세요. 커서는 불투명하므로 토큰처럼 취급하고 직접 생성하지 마세요.

속도 제한

요청은 계정 등급에 따라 분당 속도가 제한됩니다. 모든 응답에는 X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset(윈도우가 재설정되기까지의 초) 헤더가 포함됩니다. 제한을 초과하면 본문에 retry_after_seconds 값과 함께 429가 반환됩니다. 개별 키는 요청 시 더 높은 상한을 부여받을 수 있습니다.

등급분당 요청 수
Bronze60
Silver300
Gold1,000
Platinum5,000
Enterprise무제한

멱등성

쓰기 엔드포인트(예: POST /shipments)에는 Idempotency-Key 헤더가 필요합니다. 동일한 키로 요청을 재시도하면 중복을 생성하는 대신 원래 결과가 반환되므로 네트워크 재시도가 항상 안전합니다. 읽기 전용(GET) 엔드포인트에는 필요하지 않습니다.

엔드포인트

GET/health

키가 작동하는지 확인하고 현재 등급과 속도 제한 상태를 확인하세요. 연결을 검증하기 위한 가벼운 호출입니다.

bash
curl https://api.staging.mglobalship.com/api/v1/external/health \
  -H "Authorization: Bearer mgs_live_..."
json
{
  "status": "ok",
  "tenant_id": 123,
  "tier": "silver",
  "rate_limit": {
    "limit": 300,
    "remaining": 299,
    "reset_seconds": 59
  }
}
POST/shipments

배송을 등록하면 플랫폼이 추적을 시작합니다. shipments.write 범위와 고유한 Idempotency-Key 헤더가 필요합니다. 이 배송은 요금제의 월간 할당량에 포함됩니다.

매개변수유형설명
Idempotency-Key*string (header)요청마다 고유한 값입니다. 동일한 값으로 재시도하면 중복을 생성하는 대신 원래 배송이 반환됩니다.
tracking_number*stringAWB / B-L / 추적 번호입니다.
carrier_code*string운송업체 또는 항공사 코드(PCS 코드, IATA 항공사 코드 또는 AfterShip courier 슬러그).
mode*string운송 모드: sea, air 또는 courier.
bash
curl -X POST https://api.staging.mglobalship.com/api/v1/external/shipments \
  -H "Authorization: Bearer mgs_live_..." \
  -H "Idempotency-Key: a1b2c3d4-e5f6-7890" \
  -H "Content-Type: application/json" \
  -d '{
    "tracking_number": "160-12345675",
    "carrier_code": "pcs",
    "mode": "air"
  }'
json
{
  "object": "shipment",
  "id": 12346,
  "tracking_number": "160-12345675",
  "carrier_code": "pcs",
  "mode": "air",
  "status": "pending",
  "awb_number": "160-12345675",
  "_links": {
    "self": "/api/v1/external/shipments/12346",
    "tracking": "/api/v1/external/shipments/12346/tracking"
  }
}
GET/shipments

최신순으로 배송 목록을 조회합니다. 커서 페이지네이션과 선택적 필터를 지원합니다.

매개변수유형설명
limitinteger1–100, 기본값 20.
cursorstring이전 페이지에서 받은 불투명 커서.
statusstring배송 상태로 필터링합니다. 예: in_transit.
qstring배송 필드 전반에 대한 전문 검색.
modestringair, sea, rail 또는 road.
carrier_codestring운송업체로 필터링합니다. 예: maersk.
postring발주 번호로 필터링합니다.
bash
curl "https://api.staging.mglobalship.com/api/v1/external/shipments?status=in_transit&limit=20" \
  -H "Authorization: Bearer mgs_live_..."
json
{
  "object": "list",
  "data": [
    {
      "object": "shipment",
      "id": 12345,
      "tracking_number": "MAEU1234567",
      "carrier_code": "maersk",
      "mode": "sea",
      "status": "in_transit",
      "origin": { "country": "CN", "city": "Shanghai", "port_code": "CNSHA" },
      "destination": { "country": "MY", "city": "Port Klang", "port_code": "MYPKG" },
      "po_number": "PO-2026-001",
      "estimated_arrival": "2026-04-30T14:00:00+08:00",
      "_links": {
        "self": "/api/v1/external/shipments/12345",
        "tracking": "/api/v1/external/shipments/12345/tracking"
      }
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "_links": { "self": "/api/v1/external/shipments" }
}
GET/shipments/{id}

전체 화물 세부 정보와 마일스톤 이력을 포함하여 단일 배송을 조회합니다.

매개변수유형설명
id*integer배송 id(경로 매개변수).
bash
curl https://api.staging.mglobalship.com/api/v1/external/shipments/12345 \
  -H "Authorization: Bearer mgs_live_..."
json
{
  "object": "shipment",
  "id": 12345,
  "tracking_number": "MAEU1234567",
  "carrier_code": "maersk",
  "mode": "sea",
  "status": "in_transit",
  "origin": { "country": "CN", "city": "Shanghai", "port_code": "CNSHA" },
  "destination": { "country": "MY", "city": "Port Klang", "port_code": "MYPKG" },
  "po_number": "PO-2026-001",
  "container_no": "MAEU123456789",
  "estimated_arrival": "2026-04-30T14:00:00+08:00",
  "vessel_name": "MSC GULSUN",
  "voyage_number": "2026W0105",
  "cargo": {
    "weight_kg": 18000.5,
    "volume_cbm": 45.25,
    "pieces": 120,
    "description": "Electronics",
    "hs_code": "8471.30",
    "container_size": "40HQ",
    "declared_value": { "amount": 499900, "currency": "USD" }
  },
  "milestones": [
    {
      "object": "milestone",
      "status_code": "PICKED_UP",
      "status_text": "Picked up",
      "location": "Shanghai",
      "occurred_at": "2026-04-22T08:15:00+08:00",
      "source": "maersk_direct_api"
    }
  ],
  "_links": {
    "self": "/api/v1/external/shipments/12345",
    "tracking": "/api/v1/external/shipments/12345/tracking"
  }
}
GET/shipments/{id}/weather

배송의 출발지와 목적지에서 현재/예보 날씨(Open-Meteo)를 가져옵니다. 온디맨드 보강이며 약 30분 캐시됩니다. 구간의 위치를 확인할 수 없는 경우 해당 구간은 null입니다.

매개변수유형설명
id*integer배송 id(경로 매개변수).
bash
curl https://api.staging.mglobalship.com/api/v1/external/shipments/12345/weather \
  -H "Authorization: Bearer mgs_live_..."
json
{
  "object": "weather",
  "shipment_id": 12345,
  "origin": {
    "label": "Singapore, SG",
    "lat": 1.29,
    "lng": 103.85,
    "observed_at": "2026-06-25T12:00:00+00:00",
    "temperature_c": 29.4,
    "wind_mps": 2.7,
    "condition_id": 803,
    "condition_main": "Clouds",
    "severity": "low",
    "summary": "Clouds",
    "alerts_count": 0
  },
  "destination": {
    "label": "New York, US",
    "lat": 40.71,
    "lng": -74.0,
    "observed_at": "2026-06-25T12:00:00+00:00",
    "temperature_c": 17.1,
    "wind_mps": 0.5,
    "condition_id": 803,
    "condition_main": "Clouds",
    "severity": "low",
    "summary": "Clouds",
    "alerts_count": 0
  },
  "_links": {
    "self": "/api/v1/external/shipments/12345/weather",
    "shipment": "/api/v1/external/shipments/12345"
  }
}
GET/shipments/{id}/risk

배송의 출발지와 목적지 인근(최근 7 days 동안 100 km 이내)의 분쟁/시민 소요 이벤트를 가져옵니다. 제공자 결과를 캐시하는 온디맨드 보강입니다.

매개변수유형설명
id*integer배송 id(경로 매개변수).
bash
curl https://api.staging.mglobalship.com/api/v1/external/shipments/12345/risk \
  -H "Authorization: Bearer mgs_live_..."
json
{
  "object": "geopolitical_risk",
  "shipment_id": 12345,
  "origin": {
    "label": "Singapore, SG",
    "lat": 1.29,
    "lng": 103.85,
    "observed_at": "2026-06-25T12:00:00+00:00",
    "severity": "high",
    "radius_km": 100,
    "since_days": 7,
    "summary": "High: 1 violence_civilians event",
    "events_count": 1,
    "top_events": [
      {
        "occurred_on": "2026-06-21",
        "type": "violence_civilians",
        "sub_type": "Attack",
        "location": "Singapore",
        "fatalities": 0,
        "distance_km": 12.0,
        "description": "High: 1 violence_civilians event"
      }
    ]
  },
  "destination": null,
  "_links": {
    "self": "/api/v1/external/shipments/12345/risk",
    "shipment": "/api/v1/external/shipments/12345"
  }
}
GET/shipments/{id}/tracking

배송에 대한 간결한 추적 타임라인(순서가 지정된 마일스톤 이벤트)을 가져옵니다.

매개변수유형설명
id*integer배송 id(경로 매개변수).
bash
curl https://api.staging.mglobalship.com/api/v1/external/shipments/12345/tracking \
  -H "Authorization: Bearer mgs_live_..."
json
{
  "object": "tracking",
  "shipment_id": 12345,
  "status": "in_transit",
  "estimated_arrival": "2026-04-30T14:00:00+08:00",
  "last_event_at": "2026-04-23T06:00:00+08:00",
  "events": [
    {
      "object": "milestone",
      "status_code": "PICKED_UP",
      "status_text": "Picked up at origin",
      "location": "Shanghai",
      "occurred_at": "2026-04-22T08:15:00+08:00",
      "source": "maersk_direct_api"
    },
    {
      "object": "milestone",
      "status_code": "DEPARTED_ORIGIN",
      "status_text": "Departed origin port",
      "location": "Shanghai",
      "occurred_at": "2026-04-23T06:00:00+08:00",
      "source": "maersk_direct_api"
    }
  ],
  "_links": {
    "self": "/api/v1/external/shipments/12345/tracking",
    "shipment": "/api/v1/external/shipments/12345"
  }
}

웹훅

폴링하는 대신 웹훅을 구독하면 어떤 일이 발생했을 때, 예를 들어 배송에 예외가 발생했을 때 알림을 받을 수 있습니다. API Portal에서 엔드포인트 URL을 구성하고 이벤트 유형을 선택하면, 각 이벤트마다 여러분의 URL로 JSON 페이로드를 POST합니다.

모든 전송은 서명되어 있어 당사로부터 온 것임을 검증할 수 있습니다. 서명은 X-MGS-Signature 헤더로, 이벤트 유형은 X-MGS-Event로, 고유한 전송 id는 X-MGS-Delivery-Id로 전송됩니다(이를 재사용하여 핸들러를 멱등하게 만드세요). 전송은 24시간에 걸쳐 지수 백오프로 재시도됩니다.

X-MGS-Signature는 t=<timestamp>,v1=<signature> 형식을 가지며, 여기서 signature는 엔드포인트 시크릿을 키로 사용한 문자열 "<timestamp>.<raw-request-body>"의 16진수 HMAC-SHA256입니다. 검증 방법: t와 v1을 분리하고, 타임스탬프와 리터럴 점, 그리고 정확한 원본 본문에 대해 HMAC을 다시 계산한 후 비교하세요. 일치하지 않거나 타임스탬프가 너무 오래된 경우 거부하세요.

http
X-MGS-Event: shipment.exception
X-MGS-Delivery-Id: whd_8f3c2a1b
X-MGS-Signature: t=1715241600,v1=4e2c...hex...sha256

오류

오류는 표준 HTTP 상태 코드와 일관된 JSON 봉투를 사용합니다. 오류 객체는 항상 안정적인 code와 사람이 읽을 수 있는 메시지를 포함하며, 일부 오류는 컨텍스트 필드를 추가합니다. 모든 응답에는 request_id가 포함됩니다. 지원팀에 문의할 때 이를 함께 알려주세요.

상태코드발생 시점
400validation_error요청 본문이 없거나 유효하지 않습니다(또는 Idempotency-Key 헤더가 없습니다).
401auth.token_invalidAPI 키가 없거나 유효하지 않습니다.
402shipment.overage_payment_required배송 할당량이 소진되었습니다. 먼저 미결제 초과분을 정산하세요.
403auth.insufficient_scope키에 필요한 범위가 없습니다. 예: shipments.read.
403auth.tenant_suspended테넌트 계정이 활성 상태가 아닙니다.
404shipment.not_found요청한 리소스가 존재하지 않습니다.
409shipment.duplicate이 추적 번호와 운송업체의 배송이 이미 존재합니다.
429rate_limit_exceeded속도 제한에 도달했습니다. retry_after_seconds를 참조하세요.
json
{
  "error": {
    "code": "auth.token_invalid",
    "message": "Token invalid."
  },
  "request_id": "req_9a8b7c6d"
}
json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded for Silver tier (300 req/min). Wait 23s.",
    "retry_after_seconds": 23
  },
  "request_id": "req_1f2e3d4c"
}

시작하기