The error every Duffel function returns when something goes wrong.
A failed call always gives you {:error, %Duffel.Error{}}, whether the
API rejected the request or the request never reached it, so one clause
covers both:
case Duffel.Orders.create(client, params) do
{:ok, order} -> ...
{:error, %Duffel.Error{type: :rate_limit_error}} -> retry_later()
{:error, %Duffel.Error{type: :validation_error, source: source}} -> ...
{:error, %Duffel.Error{type: :transport_error}} -> retry_later()
endAPI errors
These mirror the Duffel error schema.
The struct fields come from the first error in the response; the full
list is under :errors, and :status holds the HTTP status.
:request_id identifies the request to Duffel support, and is read from
the response body, or from the x-request-id header Duffel sets on
every response when the body carries no id. :type is
one of :airline_error, :api_error, :authentication_error,
:invalid_request_error, :invalid_state_error, :rate_limit_error or
:validation_error. A type Duffel adds later reads as :unknown_error.
Transport errors
When the request could not be completed at all — connection refused, DNS
failure, timeout — :type is :transport_error and :status is nil.
The underlying exception, usually a Req.TransportError, is kept under
:reason for when you need to tell those cases apart.
Rate limits
:rate_limit holds a Duffel.RateLimit whenever the response reported
your remaining allowance, which is most useful on a
:rate_limit_error:
{:error, %Duffel.Error{type: :rate_limit_error, rate_limit: rate_limit}} ->
retry_in(rate_limit.retry_after_ms)Unexpected responses
Duffel wraps every resource in a data envelope. A success response
without one means the endpoint returned something this library does not
know how to read, so :type is :unexpected_response and the body is
kept under :reason.
Summary
Types
@type t() :: %Duffel.Error{ __exception__: true, code: String.t() | nil, documentation_url: String.t() | nil, errors: [map()], message: String.t() | nil, rate_limit: Duffel.RateLimit.t() | nil, reason: term(), request_id: String.t() | nil, source: map() | nil, status: pos_integer() | nil, title: String.t() | nil, type: atom() | nil }