Builds and sends requests to the Moov API.
Every Moov.* resource module (Moov.Accounts, Moov.Transfers, ...) is a
thin, documented wrapper around this module - you can always drop down to
request/4 directly for an endpoint that doesn't have a dedicated wrapper
yet, or to pass low-level options none of the wrappers expose.
Creating a client
# explicit credentials
client = Moov.Client.new(public_key: "...", private_key: "...")
# or pull defaults from `config :moov, ...` (see `Moov.Config`)
client = Moov.Client.new()
# client-side / Moov.js flows authenticate with a bearer token instead
client = Moov.Client.new(access_token: token)A Moov.Client is a plain, immutable struct - hold on to it, store it in
a GenServer's state, build a fresh one per request, whatever suits your
application. Nothing about this library requires a singleton or an OTP
application tree.
Sending requests
Moov.Client.get(client, "/accounts/#{account_id}")
Moov.Client.post(client, "/accounts", %{account_type: "individual", ...})
Moov.Client.patch(client, "/accounts/#{account_id}", %{profile: ...})
Moov.Client.delete(client, "/accounts/#{account_id}")All of these (and request/4 itself) return {:ok, body} on any 2xx
response or {:error, %Moov.Error{}} otherwise. body is the decoded JSON
response with its original camelCase string keys, exactly as Moov sent it.
Raise instead of pattern matching with Moov.unwrap!/1.
Request options
Every sending function accepts:
:query- a map or keyword list of query string parameters:headers- a list of{name, value}tuples to merge in (these win over any header this module sets, except where noted):idempotent- whentrueand no:idempotency_keyis given, a random UUID v4 is generated once and reused across all retry attempts for this call.Moov.Transfers.create/3sets this for you:idempotency_key- an explicitX-Idempotency-Keyvalue, e.g. one derived from your own job/event ID so retries across process restarts stay deduplicated too:wait_for- set to"rail-response"to add theX-Wait-Forheader Moov's transfer/refund endpoints use to opt into a slower, fully populated synchronous response:form_multipart- for multipart file uploads (Moov.Files,Moov.Images, dispute evidence), e.g.form_multipart: [file: {binary, filename: "id.png", content_type: "image/png"}]. Mutually exclusive with:jsonfor a given call:api_version,:max_retries,:receive_timeout- per-call overrides of the client's defaults
Summary
Functions
Sends a DELETE request.
Sends a GET request. See the moduledoc for shared options.
Builds a new client.
Sends a PATCH request with body as the JSON payload.
Sends a POST request with body as the JSON payload.
Sends a PUT request with body as the JSON payload.
The low-level entry point every other function in this module (and every
Moov.* resource wrapper) ultimately calls. See the moduledoc for the
full list of supported opts.
Types
@type method() :: :get | :post | :patch | :put | :delete
Functions
@spec delete(t(), String.t(), keyword()) :: {:ok, term()} | {:error, Moov.Error.t()}
Sends a DELETE request.
@spec get(t(), String.t(), keyword()) :: {:ok, term()} | {:error, Moov.Error.t()}
Sends a GET request. See the moduledoc for shared options.
Builds a new client.
Accepts everything Moov.Config resolves from application environment,
plus:
:base_url- defaults to"https://api.moov.io":api_version- theX-Moov-Versionto send on every request. Always set this explicitly in production - Moov silently falls back to legacyv2024.01.00behavior if it's omitted entirely, which this library never does, but it's worth knowing the API does:public_key/:private_key- Basic Auth credentials (server-side integrations):access_token- a bearer token (client-side / Moov.js integrations, typically obtained viaMoov.AccessTokens.create/2); takes precedence over:public_key/:private_keyif both are given:max_retries- default number of retries for transient failures (default:3):receive_timeout- default response timeout in milliseconds (default:30_000):req_options- a keyword list merged into everyReq.request/1call, e.g.req_options: [plug: {Req.Test, MyApp.MoovStub}]in tests, orreq_options: [connect_options: [proxy: ...]]behind a corporate proxy
Sends a PATCH request with body as the JSON payload.
Sends a POST request with body as the JSON payload.
Sends a PUT request with body as the JSON payload.
The low-level entry point every other function in this module (and every
Moov.* resource wrapper) ultimately calls. See the moduledoc for the
full list of supported opts.