Move money between two payment methods. This is the core primitive everything else in money movement (sweeps, refunds, schedules, payment links, invoices) is built on top of.
Summary
Functions
Cancels a transfer that hasn't settled yet (e.g. a queued ACH debit).
Creates a transfer.
Creates a transfer configuration for an account (default behavior for transfers it facilitates, e.g. default facilitator fees).
Retrieves a single transfer.
Gets the details of a transfer cancellation.
Gets an account's transfer configuration.
Retrieves the available transfer options (eligible rails, estimated
fees/timing) for a prospective source/destination/amount, without
actually creating a transfer. Same params shape as create/4.
Lists transfers. Filter with opts[:query], e.g. query: [status: "failed"].
Updates a transfer's :metadata or :description (not its amount or parties, which are immutable).
Updates an account's transfer configuration.
Functions
@spec cancel(Moov.Client.t(), String.t(), String.t()) :: {:ok, map()} | {:error, Moov.Error.t()}
Cancels a transfer that hasn't settled yet (e.g. a queued ACH debit).
@spec create(Moov.Client.t(), String.t(), map(), keyword()) :: {:ok, map()} | {:error, Moov.Error.t()}
Creates a transfer.
params:
:source/:destination- each%{payment_method_id: id}. A:transfer_idmay be given as the source instead, linking this transfer into the same transfer group as an earlier one (e.g. for multi-party split payments). The source may alternatively be a:payment_tokencollected via Moov.js:amount-%{currency: "USD", value: 1204}(an integer in minor units - cents for USD):description,:metadata,:foreign_id- optional bookkeeping fields:amount_details- e.g.%{tip: 100}:sales_tax_amount,:line_items- itemized purchase detail; if given,line_itemsamounts plussales_tax_amountmust sum to:amount:facilitator_fee-%{total: 50}or%{markup: 25}:ach_details-%{sec_code: "WEB", debit_hold_period: "..."}:card_details-%{dynamic_descriptor: "...", transaction_source: "..."}
Options
:idempotent- defaults totruefor this function specifically, since Moov requires anX-Idempotency-Keyon transfer creation. Pass your own:idempotency_key(e.g. derived from your own order/job ID) to make retries safe across process restarts, not just within a single call:wait_for- pass"rail-response"to receive a fully populated, synchronous response (rail-specific status, auth codes, etc) instead of just%{"transferID" => ..., "createdOn" => ...}. Moov enforces a 15-second timeout for this; on timeout you still get a202with the transfer ID, so always handle the "thin" response shape too
Examples
Moov.Transfers.create(client, account_id, %{
source: %{payment_method_id: payer_payment_method_id},
destination: %{payment_method_id: payee_payment_method_id},
amount: %{currency: "USD", value: 1500},
description: "Order #1234"
})
# ask for the full synchronous response
Moov.Transfers.create(client, account_id, params, wait_for: "rail-response")
@spec create_transfer_config(Moov.Client.t(), String.t(), map()) :: {:ok, map()} | {:error, Moov.Error.t()}
Creates a transfer configuration for an account (default behavior for transfers it facilitates, e.g. default facilitator fees).
@spec get(Moov.Client.t(), String.t(), String.t()) :: {:ok, map()} | {:error, Moov.Error.t()}
Retrieves a single transfer.
@spec get_cancellation(Moov.Client.t(), String.t(), String.t(), String.t()) :: {:ok, map()} | {:error, Moov.Error.t()}
Gets the details of a transfer cancellation.
@spec get_transfer_config(Moov.Client.t(), String.t()) :: {:ok, map()} | {:error, Moov.Error.t()}
Gets an account's transfer configuration.
@spec get_transfer_options(Moov.Client.t(), String.t(), map()) :: {:ok, map()} | {:error, Moov.Error.t()}
Retrieves the available transfer options (eligible rails, estimated
fees/timing) for a prospective source/destination/amount, without
actually creating a transfer. Same params shape as create/4.
@spec list(Moov.Client.t(), String.t(), keyword()) :: {:ok, [map()]} | {:error, Moov.Error.t()}
Lists transfers. Filter with opts[:query], e.g. query: [status: "failed"].
@spec update(Moov.Client.t(), String.t(), String.t(), map()) :: {:ok, map()} | {:error, Moov.Error.t()}
Updates a transfer's :metadata or :description (not its amount or parties, which are immutable).
@spec update_transfer_config(Moov.Client.t(), String.t(), map()) :: {:ok, map()} | {:error, Moov.Error.t()}
Updates an account's transfer configuration.