Req-based HTTP transport. Retries GET on transient errors; no retry for mutating verbs.
All functions accept per-call opts overriding the client configuration:
:access_token- token for this request only:custom_headers- headers merged over the client'scustom_headers, overriding generated headers case-insensitively:timeout- receive timeout in milliseconds for this request only:max_retries- GET retry budget for this request only:retry_delay- base backoff in milliseconds for this request only:max_retry_delay- backoff ceiling in milliseconds for this request only
Retry policy
A GET is retried while the response status is one of
[429, 500, 502, 503, 504] or the request fails with a retryable
transport error (a connection closed under the pool, a refused or unreachable
host). A :timeout is never retried: the receive timeout has already spent
the latency budget.
Backoff is exponential from :retry_delay, doubled per attempt, capped by
:max_retry_delay, plus jitter so that concurrent callers do not come back
in lockstep after an incident. A Retry-After header (delta-seconds form)
takes precedence, but is capped by :max_retry_delay all the same.
The wait blocks the calling process, so the worst-case latency of a GET is
roughly max_retries * timeout plus the accumulated backoff.
Telemetry
Every attempt — including each retry — is wrapped in a :telemetry.span/3:
[:mercadopago, :request, :start]- measurements%{system_time: _}[:mercadopago, :request, :stop]- measurements%{duration: _}[:mercadopago, :request, :exception]- when the request raises
Metadata carries :method, :path and :attempt (zero-based), plus
:status on a completed request or :error on a transport failure. Neither
the access token nor the request body is ever included.
Summary
Types
Request body: a JSON-encodable map, a multipart body, or none.
A MercadoPago resource identifier. The API returns some ids as integers.
A multipart/form-data body. Each part is {name, value}, where name is an
atom (Req's requirement) and value is either a plain binary field or
{content, filename: name, content_type: type} for a file part. content may
be a binary or a stream, so large uploads need not be read into memory.
Result of an API call. {:ok, ...} carries the HTTP status and the response
body: a map or a list for JSON, nil for an empty body, and a raw binary
when the response is not JSON (an HTML error page from a proxy, for
instance). {:error, reason} is returned for transport-level failures
(timeouts, connection errors).
Functions
DELETE request.
GET request with optional query params and per-call opts.
PATCH request, for endpoints that accept a partial update.
POST request. Omit body or pass nil to send no body.
PUT request.
Converts a response into idiomatic {:ok, body} / {:error, exception}.
Types
@type body() :: map() | multipart_body() | nil
Request body: a JSON-encodable map, a multipart body, or none.
@type id() :: String.t() | non_neg_integer()
A MercadoPago resource identifier. The API returns some ids as integers.
A multipart/form-data body. Each part is {name, value}, where name is an
atom (Req's requirement) and value is either a plain binary field or
{content, filename: name, content_type: type} for a file part. content may
be a binary or a stream, so large uploads need not be read into memory.
Required by endpoints such as chargeback documentation upload:
{:multipart, [
{:kind, "invoice"},
{:file, {File.stream!("proof.pdf", 2048), filename: "proof.pdf",
content_type: "application/pdf"}}
]}
@type response() :: {:ok, %{status: non_neg_integer(), response: map() | list() | binary() | nil}} | {:error, term()}
Result of an API call. {:ok, ...} carries the HTTP status and the response
body: a map or a list for JSON, nil for an empty body, and a raw binary
when the response is not JSON (an HTML error page from a proxy, for
instance). {:error, reason} is returned for transport-level failures
(timeouts, connection errors).
Functions
@spec delete(Mercadopago.Client.t(), String.t(), keyword()) :: response()
DELETE request.
@spec get(Mercadopago.Client.t(), String.t(), map() | nil, keyword()) :: response()
GET request with optional query params and per-call opts.
@spec patch(Mercadopago.Client.t(), String.t(), body(), keyword()) :: response()
PATCH request, for endpoints that accept a partial update.
@spec post(Mercadopago.Client.t(), String.t(), body(), keyword()) :: response()
POST request. Omit body or pass nil to send no body.
Pass {:multipart, parts} as the body to upload files as multipart/form-data
instead of JSON — see multipart_body/0.
@spec put(Mercadopago.Client.t(), String.t(), body(), keyword()) :: response()
PUT request.
Converts a response into idiomatic {:ok, body} / {:error, exception}.
A completed request with a status of 400 or above becomes
{:error, %Mercadopago.Error{}}; a success is unwrapped to its body alone.
Transport failures pass through unchanged, since they are already {:error, _}.
client
|> Mercadopago.Payment.get(payment_id)
|> Mercadopago.HTTP.unwrap()This is a pure function over an already-returned response, so it is opt-in: the
resource functions themselves keep returning {:ok, %{status: _, response: _}}.
Reach for it when the status code carries no information you act on.