Skip to content
Business
Skill

/duffel

Real-time GDS flight search via Duffel API. Accurate per-fare-class pricing, cabin selection, multi-city, time preferences. Primary cash price source. Does not include Southwest.

BOOST
From plugin
travel-hacker
69748 skills1 agent6 MCP
Install
$ npx -y skills add borski/travel-hacking-toolkit --skill duffel --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/duffel

Context preview

The summary Claude sees to decide when to auto-load this skill.

Real-time GDS flight search via Duffel API. Accurate per-fare-class pricing, cabin selection, multi-city, time preferences. Primary cash price source. Does not include Southwest.

SKILL.md

duffel.SKILL.md
name: duffel
description: Real-time GDS flight search via Duffel API. Accurate per-fare-class pricing, cabin selection, multi-city, time preferences. Primary cash price source. Does not include Southwest.
category: flights
summary: Primary cash prices. Real GDS per-fare-class data.
api_key: Duffel
allowed-tools: Bash(curl *)

Duffel Flights

Search for real-time flight offers across airlines via the [Duffel API](https://duffel.com/docs/api). Returns live pricing, cabin details, baggage info, and booking links. Supports one-way, round-trip, and multi-city searches.

**Source:** [duffel.com](https://duffel.com)

Prerequisites

  • `DUFFEL_API_KEY_LIVE` environment variable set with a live API token
  • Token needs `air.offer_requests.create` permission

API Basics

  • **Base URL:** `https://api.duffel.com`
  • **Version header:** `Duffel-Version: v2` (REQUIRED, v1 is deprecated)
  • **Auth:** `Authorization: Bearer $DUFFEL_API_KEY_LIVE`
  • **Content-Type:** `application/json`
  • **Rate limit:** 60 requests per 60 seconds

Search Flights (One-Way)

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"
    }
  }'

Search Flights (Round-Trip)

Add a second slice with origin/destination reversed:

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"
    }
  }'

Search Flights (Multi-City)

Add as many slices as needed:

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"
    }
  }'

Nonstop Only

Set `max_connections` to 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
    }
  }'

Multiple Passengers

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

Use `age` instead of `type` for children to avoid passenger type mismatches between search and booking.

Time Preferences

Constrain departure or arrival times:

"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"}
}]

Query Parameters

| Parameter | Default | Description | |-----------|---------|-------------| | `return_offers` | `true` | Set to `false` to get just the request ID, then fetch offers separately | | `supplier_timeout` | `20000` | Max ms to wait for airline responses (2000 to 60000) |

Reading the Response

The response is nested under `data`. Key fields:

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

Get Offer Details

Retrieve full details for a specific offer:

Read more
Ships withtravel-hacker

AI-powered travel hacking with points, miles, and award flights. Drop-in skills and MCP servers for OpenCode, Claude Code, and Codex. Ask your AI to find you a 60,000-mile business class flight to Tokyo.

Get the whole plugin

Other skills on travel-hacker.