
Duffel
- 36 installs
- 76 repo stars
- Updated August 4, 2026
- vm0-ai/vm0-skills
Helps with ai & agent building tasks.
About
duffel is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- duffel
- AI & Agent Building
- AI-coding skill
Duffel by the numbers
- 36 all-time installs (skills.sh)
- Ranked #8,638 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vm0-ai/vm0-skills --skill duffelAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 36 |
|---|---|
| repo stars | ★ 76 |
| Last updated | August 4, 2026 |
| Repository | vm0-ai/vm0-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Troubleshooting
If requests fail, run zero doctor check-connector --env-name DUFFEL_TOKEN or zero doctor check-connector --url https://api.duffel.com/air/airlines --method GET
Authentication
All requests require an access token passed in the Authorization header using the Bearer scheme, plus a Duffel-Version header to pin the API version.
Authorization: Bearer $DUFFEL_TOKEN
Duffel-Version: v2Tokens starting with duffel_test_ access test mode (sandbox airlines, fake cards); tokens starting with duffel_live_ access live mode. Test mode cannot be used with live tokens, and vice versa.
Official docs: https://duffel.com/docs/api
Flights
Booking a flight follows this flow: create an offer request → pick an offer → create an order → optionally cancel it.
1. Create Offer Request (search flights)
Write to /tmp/duffel_request.json:
{
"data": {
"passengers": [
{ "type": "adult" }
],
"slices": [
{
"origin": "LHR",
"destination": "JFK",
"departure_date": "<your-departure-date>"
}
],
"cabin_class": "economy"
}
}Then run:
curl -s -X POST "https://api.duffel.com/air/offer_requests" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2" --header "Content-Type: application/json" -d @/tmp/duffel_request.jsonThe response contains an offer_request.id (orq_...) and the first page of offers. For multi-city or return trips, add more entries to slices.
2. List Offers for a Request
Fetch more offers (with pagination, sorting, filtering) for the same offer request:
curl -s "https://api.duffel.com/air/offers?offer_request_id=<your-offer-request-id>&limit=50&sort=total_amount" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"Useful query params:
| Param | Description |
|---|---|
offer_request_id | Required — scope results to one request |
limit | 1–200 (default 50) |
sort | total_amount or total_duration |
max_connections | 0, 1, or 2 |
after / before | Pagination cursors |
3. Get a Single Offer
curl -s "https://api.duffel.com/air/offers/<your-offer-id>?return_available_services=true" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"return_available_services=true includes ancillaries (bags, seats) you can add when creating the order.
4. Create Order (book the flight)
Replace <your-offer-id> and passenger fields with real values. Passenger IDs come from the offer response (offer.passengers[].id).
Write to /tmp/duffel_request.json:
{
"data": {
"type": "instant",
"selected_offers": ["<your-offer-id>"],
"passengers": [
{
"id": "<your-offer-passenger-id>",
"given_name": "Jane",
"family_name": "Doe",
"title": "ms",
"gender": "f",
"born_on": "1990-01-15",
"email": "jane@example.com",
"phone_number": "+14155551234"
}
],
"payments": [
{
"type": "balance",
"amount": "<your-offer-total-amount>",
"currency": "<your-offer-total-currency>"
}
]
}
}Then run:
curl -s -X POST "https://api.duffel.com/air/orders" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2" --header "Content-Type: application/json" -d @/tmp/duffel_request.jsonpayments[].type is usually balance (drawn from your Duffel account balance). The amount and currency must match the offer's total_amount / total_currency.
5. Get Order
curl -s "https://api.duffel.com/air/orders/<your-order-id>" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"6. List Orders
curl -s "https://api.duffel.com/air/orders?limit=50" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"7. Cancel Order
Cancellation is two steps: create a pending cancellation (to preview the refund), then confirm it.
Create pending cancellation:
Write to /tmp/duffel_request.json:
{
"data": {
"order_id": "<your-order-id>"
}
}Then run:
curl -s -X POST "https://api.duffel.com/air/order_cancellations" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2" --header "Content-Type: application/json" -d @/tmp/duffel_request.jsonThe response includes a refund_amount preview and a cancellation id (ore_...). Confirm it to actually cancel:
curl -s -X POST "https://api.duffel.com/air/order_cancellations/<your-cancellation-id>/actions/confirm" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"8. Seat Maps (optional)
curl -s "https://api.duffel.com/air/seat_maps?offer_id=<your-offer-id>" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"Stays (Hotels)
Booking a stay follows this flow: search → fetch all rates → create quote → create booking.
1. Search Stays
Write to /tmp/duffel_request.json:
{
"data": {
"rooms": 1,
"location": {
"radius": 5,
"geographic_coordinates": {
"latitude": 51.5071,
"longitude": -0.1416
}
},
"check_in_date": "<your-check-in-date>",
"check_out_date": "<your-check-out-date>",
"guests": [
{ "type": "adult" }
]
}
}Then run:
curl -s -X POST "https://api.duffel.com/stays/search" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2" --header "Content-Type: application/json" -d @/tmp/duffel_request.jsonEach result has a search_result_id (srr_...) and cheapest_rate_total_amount. To search by a specific property instead of an area, swap location for accommodation.id (obtained from Accommodation endpoints).
2. Fetch All Rates for a Search Result
The search response only contains the cheapest rate. To see all available rooms and rates, call:
curl -s -X POST "https://api.duffel.com/stays/search_results/<your-search-result-id>/actions/fetch_all_rates" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"Each rate in the response has a rate.id (rat_...) you will quote.
3. Create Quote
A quote locks in the price and availability for a rate.
Write to /tmp/duffel_request.json:
{
"data": {
"rate_id": "<your-rate-id>"
}
}Then run:
curl -s -X POST "https://api.duffel.com/stays/quotes" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2" --header "Content-Type: application/json" -d @/tmp/duffel_request.jsonThe response contains quote.id (quo_...), valid for a short window (minutes).
4. Create Booking
Write to /tmp/duffel_request.json:
{
"data": {
"quote_id": "<your-quote-id>",
"guests": [
{
"given_name": "Jane",
"family_name": "Doe",
"born_on": "1990-01-15"
}
],
"email": "jane@example.com",
"phone_number": "+14155551234",
"accommodation_special_requests": "Late check-in"
}
}Then run:
curl -s -X POST "https://api.duffel.com/stays/bookings" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2" --header "Content-Type: application/json" -d @/tmp/duffel_request.json5. Get / List / Cancel Booking
curl -s "https://api.duffel.com/stays/bookings/<your-booking-id>" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"curl -s "https://api.duffel.com/stays/bookings?limit=50" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"curl -s -X POST "https://api.duffel.com/stays/bookings/<your-booking-id>/actions/cancel" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"Supporting Resources
List Airlines
curl -s "https://api.duffel.com/air/airlines?limit=200" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"Lookup Aircraft
curl -s "https://api.duffel.com/air/aircraft/<your-aircraft-id>" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"Lookup Airport / Place
curl -s "https://api.duffel.com/places/suggestions?query=london" --header "Authorization: Bearer $DUFFEL_TOKEN" --header "Duffel-Version: v2"query accepts a city name, airport code, or free text; responses include IATA codes to plug into slices[].origin / destination.
Response Codes
| Status | Description |
|---|---|
200 | Success |
201 | Created (orders, bookings, quotes) |
400 | Invalid request body |
401 | Missing or invalid Authorization header |
404 | Resource not found |
422 | Validation failed (e.g. passenger missing required field) |
429 | Rate limit exceeded |
5xx | Server / airline error |
Guidelines
1. Always send `Duffel-Version: v2` — requests without it are rejected. 2. Test vs live — a duffel_test_ token cannot see orders created with a duffel_live_ token, and vice versa. 3. Offers expire — after a few minutes, an offer can no longer be booked. Re-run the offer request if you hit expiration. 4. Order `payments.amount` must match the offer's `total_amount` exactly, including decimal places. 5. Stays quotes expire within minutes — create the booking promptly after quoting. 6. Cancellations are two-step (create pending, then confirm) so you can show the refund amount before committing. 7. Use the IATA 3-letter airport code in origin/destination (e.g. LHR, JFK). Use /places/suggestions to look up codes from free-text input.
API Reference
- Overview: https://duffel.com/docs/api
- Offer Requests: https://duffel.com/docs/api/v2/offer-requests
- Offers: https://duffel.com/docs/api/v2/offers
- Orders: https://duffel.com/docs/api/v2/orders
- Order Cancellations: https://duffel.com/docs/api/order-cancellations
- Stays Search: https://duffel.com/docs/api/v2/search
- Stays Bookings: https://duffel.com/docs/api/v2/bookings/get-booking
- Test mode: https://duffel.com/docs/api/overview/test-mode