mcpField
D
duffel

duffel

github.com/borski生産性78081 回インストール2 日前に更新
リポジトリ

duffel について

開発者や旅行アプリ向けの Duffel API 航空券検索スキルです。片道、往復、複数都市の検索に対応し、価格、客室クラス、手荷物、予約リンクを含むリアルタイムのオファーを返します。

主な機能

  1. 01片道、往復、複数都市の検索
  2. 02直行便と時間帯の絞り込み
  3. 03搭乗者と客室クラスの指定
  4. 04リアルタイム価格とフライト詳細
  5. 05オファー詳細の取得

活用シーン

  1. 01複数航空会社のリアルタイム便検索
  2. 02経由回数や時刻でのフライト絞り込み
  3. 03運賃と客室クラス情報の比較
  4. 04選択したオファーの詳細確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/borski/travel-hacking-toolkit --skill duffel

インストール後、Claude Code で/duffelを入力して読み込まれたか確認します。

詳細

Duffel フライト

Duffel APIを通じて、複数の航空会社のリアルタイムなフライトオファーを検索します。最新の価格、客室の詳細、手荷物情報、予約リンクを返します。片道、往復、複数都市の検索に対応しています。

ソース: duffel.com

前提条件

  • ライブ API トークンを設定した DUFFEL_API_KEY_LIVE 環境変数
  • トークンに air.offer_requests.create 権限が必要です

API の基本

  • ベース URL: https://api.duffel.com
  • バージョンヘッダー: Duffel-Version: v2(必須、v1 は非推奨です)
  • 認証: Authorization: Bearer $DUFFEL_API_KEY_LIVE
  • Content-Type: application/json
  • レート制限: 60 秒あたり 60 リクエスト

フライトを検索(片道)

curl -s -X POST "https://api.duffel.com/air/offer_requests?return_offers=true&supplier_timeout=15000" \
  -H "Accept: application/json" \
  -H "Duffel-Version: v2" \
  -H "Authorization: Bearer $DUFFEL_API_KEY_LIVE" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "slices": [{
        "origin": "SFO",
        "destination": "NRT",
        "departure_date": "2026-08-15"
      }],
      "passengers": [{"type": "adult"}],
      "cabin_class": "economy"
    }
  }'

フライトを検索(往復)

2 つ目の区間を追加し、出発地と目的地を逆にします:

curl -s -X POST "https://api.duffel.com/air/offer_requests?return_offers=true&supplier_timeout=15000" \
  -H "Accept: application/json" \
  -H "Duffel-Version: v2" \
  -H "Authorization: Bearer $DUFFEL_API_KEY_LIVE" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "slices": [
        {
          "origin": "SFO",
          "destination": "NRT",
          "departure_date": "2026-08-15"
        },
        {
          "origin": "NRT",
          "destination": "SFO",
          "departure_date": "2026-08-22"
        }
      ],
      "passengers": [{"type": "adult"}],
      "cabin_class": "business"
    }
  }'

フライトを検索(複数都市)

必要な数だけ区間を追加します:

curl -s -X POST "https://api.duffel.com/air/offer_requests?return_offers=true&supplier_timeout=15000" \
  -H "Accept: application/json" \
  -H "Duffel-Version: v2" \
  -H "Authorization: Bearer $DUFFEL_API_KEY_LIVE" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "slices": [
        {"origin": "SFO", "destination": "NRT", "departure_date": "2026-08-15"},
        {"origin": "NRT", "destination": "ICN", "departure_date": "2026-08-20"},
        {"origin": "ICN", "destination": "SFO", "departure_date": "2026-08-25"}
      ],
      "passengers": [{"type": "adult"}],
      "cabin_class": "economy"
    }
  }'

直行便のみ

max_connections を 0 に設定します:

curl -s -X POST "https://api.duffel.com/air/offer_requests?return_offers=true&supplier_timeout=15000" \
  -H "Accept: application/json" \
  -H "Duffel-Version: v2" \
  -H "Authorization: Bearer $DUFFEL_API_KEY_LIVE" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "slices": [{
        "origin": "SFO",
        "destination": "NRT",
        "departure_date": "2026-08-15"
      }],
      "passengers": [{"type": "adult"}],
      "cabin_class": "business",
      "max_connections": 0
    }
  }'

複数の乗客

"passengers": [
  {"type": "adult"},
  {"type": "adult"},
  {"age": 10},
  {"type": "infant_without_seat"}
]

検索時と予約時の乗客タイプの不一致を避けるには、子どもには type ではなく age を使用します。

時刻の指定

出発時刻または到着時刻を指定します:

"slices": [{
  "origin": "SFO",
  "destination": "NRT",
  "departure_date": "2026-08-15",
  "departure_time": {"from": "08:00", "to": "14:00"},
  "arrival_time": {"from": "06:00", "to": "18:00"}
}]

クエリパラメーター

パラメーターデフォルト説明
return_offerstruefalse に設定すると、リクエスト ID のみを取得し、オファーは別途取得します
supplier_timeout20000航空会社からの応答を待つ最大時間(ミリ秒)(2000~60000)

レスポンスの読み方

レスポンスは data の下にネストされています。主なフィールド:

data.id                              -> offer request ID
data.offers[]                        -> array of flight offers
  .id                                -> offer ID (use to get details or book)
  .total_amount / .total_currency    -> total price
  .base_amount / .base_currency      -> base fare (before tax)
  .tax_amount / .tax_currency        -> taxes
  .owner.name                        -> airline selling this
  .expires_at                        -> when offer expires
  .slices[]                          -> journey legs
    .origin.iata_code                -> departure airport
    .destination.iata_code           -> arrival airport
    .duration                        -> e.g. "PT11H30M"
    .segments[]                      -> individual flights
      .marketing_carrier.name        -> airline name
      .marketing_carrier_flight_number
      .operating_carrier.name        -> actual operating airline
      .departing_at / .arriving_at   -> datetime
      .duration                      -> segment duration
      .origin.iata_code / .destination.iata_code
      .passengers[].cabin_class      -> economy/business/first
      .passengers[].cabin.amenities  -> wifi, power, seat info
      .passengers[].baggages[]       -> checked/carry_on allowances
  .conditions                        -> refund/change policies
    .refund_before_departure.allowed
    .change_before_departure.allowed
    .change_before_departure.penalty_amount

オファーの詳細を取得

特定のオファーの詳細を取得します:

curl -s "https://api.duffel.com/air/offers/$OFFER_ID" \
  -H "Accept: application/json" \
  -H "Duffel-Version: v2" \
  -H "Authorization: Bearer $DUFFEL_API_KEY_LIVE"

解析のヒント

jq を使って、最安のオファーを 5 件抽出します:

| jq '[.data.offers | sort_by(.total_amount | tonumber) | .[:5][] | {
  price: (.total_amount + " " + .total_currency),
  airline: .owner.name,
  route: [.slices[] | (.origin.iata_code + " -> " + .destination.iata_code)],
  segments: [.slices[].segments[] | {
    flight: (.marketing_carrier.iata_code + .marketing_carrier_flight_number),
    carrier: .operating_carrier.name,
    depart: .departing_at,
    arrive: .arriving_at,
    cabin: .passengers[0].cabin_class,
    duration: .duration
  }],
  stops: ([.slices[].segments | length] | map(. - 1)),
  expires: .expires_at
}]'

客室クラス

値説明
economy標準エコノミー
premium_economyプレミアムエコノミー
businessビジネスクラス
firstファーストクラス

重要な注意事項

  • オファーはすぐに期限切れになります(通常 15~30 分)。expires_at を確認してください。
  • 運航航空会社名を必ず表示してください(米国 DOT の規制)。
  • supplier_timeout は HTTP クライアントのタイムアウトより短く設定してください。
  • 航空会社との不一致エラーを避けるには、子どもの乗客には type ではなく age を使用してください。
  • API は実際の GDS 価格を返します。これらは予約可能な価格であり、見積もりではありません。
  • Duffel は 1 回の検索で複数の航空会社の情報を集約します。

コメント