DuffelCAUTION
AI-powered travel hacking and search with cash, points, miles, and award flights. Drop-in skills and MCP servers for Claude, Codex, and OpenCode.
Overview
AI-powered travel hacking and search with cash, points, miles, and award flights. Drop-in skills and MCP servers for Claude, Codex, and OpenCode.
fda58ab480fdOBSERVED · 2026-10-14What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
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)
```bash
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:
```bash
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:
```bash
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:
```bash
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
```json
"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:
```json
"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:
```bash
Trust audit
CAUTIONgrade B · trust 89/100 Install with care. The audit found things worth knowing before you trust its output.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | NA |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (5)
.agents/skills
.claude/skills
.opencode/skills
skills
AGENTS.md
Gates applied: no_behavioural_pass.
fda58ab480fdfull audit observations/trust-audit/skill/borski__duffel.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-14 | fda58ab480fd | CAUTION | B | 89 | first audit |
Questions
What does the Duffel skill do?
AI-powered travel hacking and search with cash, points, miles, and award flights. Drop-in skills and MCP servers for Claude, Codex, and OpenCode.
Is Duffel safe to install?
With care. The audit graded it B (89/100) and found 5 things worth knowing before you trust this skill, listed below with the exact line each was found on.
What can Duffel access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
How current is this page?
The grade is for one exact copy of the source (fda58ab480fd), read on 2026-10-14. The repository is watched, and a new audit runs when it changes — this is the first audit.