HTTP client for the Duffel API built on Req.
Handles authentication, request formatting, response parsing, and error handling.
Request Format
All POST/PATCH requests wrap the payload in a data key as required by the Duffel API:
# You pass: %{check_in_date: "2025-06-01"}
# API receives: %{data: %{check_in_date: "2025-06-01"}}Response Format
Responses are parsed into {:ok, Travel.Types.DuffelResponse} tuples.
Errors are returned as {:error, Travel.Error} tuples.
Summary
Functions
Makes an HTTP request to the Duffel API.
Makes a paginated request that returns a stream of all pages.
Functions
@spec request( Travel.t(), atom(), String.t(), map() | nil, map() | nil ) :: {:ok, Travel.Types.DuffelResponse.t()} | {:error, Travel.Error.t() | term()}
Makes an HTTP request to the Duffel API.
Parameters
config- ATravelconfiguration structmethod- HTTP method (:get,:post,:patch,:delete)path- API path (e.g.,"stays/search")body- (optional) Request body, will be wrapped indatakeyquery_params- (optional) Query string parameters
Returns
{:ok, %T.DuffelResponse{}}on success{:error, %Travel.Error{}}on API error{:error, reason}on network/HTTP error
Examples
config = Travel.new(access_token: "duffel_test_xxx")
Travel.Client.request(config, :post, "stays/search", %{
location: %{...},
check_in_date: "2025-06-01",
check_out_date: "2025-06-05",
rooms: 1,
guests: [%{type: "adult"}]
})
@spec stream(Travel.t(), String.t(), map() | nil) :: Enumerable.t()
Makes a paginated request that returns a stream of all pages.
Uses cursor-based pagination. Each page is yielded as it's fetched.
Examples
config = Travel.new(access_token: "duffel_test_xxx")
Travel.Client.stream(config, "stays/bookings")
|> Enum.each(fn response ->
IO.inspect(response.data)
end)