LatticeStripe.Payout (LatticeStripe v1.7.5)

Copy Markdown View Source

Operations on Stripe Payout objects.

A Payout represents money moving from your Stripe balance to a connected bank account or debit card. Payouts are the outbound leg of money movement — inbound money arrives via Charge / PaymentIntent, and you (or Stripe's automatic schedule) trigger a Payout to settle the balance to a bank.

Key behaviors

  • Full CRUDL: create/3, retrieve/3, update/4, list/3, stream!/3.
  • cancel/4 and reverse/4 both use the canonical (client, id, params \\ %{}, opts \\ []) shape per D-03. Both endpoints accept at least expand, and reverse additionally accepts metadata.
  • The trace_id field decodes into a typed %LatticeStripe.Payout.TraceId{} — pattern-match on payout.trace_id.status to branch your reconciliation flow.
  • Unknown future fields from Stripe land in :extra (F-001).
  • require_param! validates the payout id pre-network on retrieve, update, cancel, and reverse.

Expandable references

The following fields are typed as binary() | map() | nil because Stripe returns an ID string by default and only inlines the expanded object when you pass expand: [...]:

Per D-05, these references stay polymorphic — the guide documents the "expand then cast via expected module" idiom.

Usage

client = LatticeStripe.Client.new!(api_key: "sk_live_...", finch: MyApp.Finch)

# Trigger a manual payout to the default external account
{:ok, payout} = LatticeStripe.Payout.create(client, %{
  "amount" => 5000,
  "currency" => "usd"
})

# Retrieve and branch on trace_id availability
{:ok, payout} = LatticeStripe.Payout.retrieve(client, "po_...")

case payout.trace_id do
  %LatticeStripe.Payout.TraceId{status: "supported", value: trace} ->
    reconcile(trace)

  %LatticeStripe.Payout.TraceId{status: "pending"} ->
    # Stripe will populate trace_id asynchronously — listen for payout.updated
    :wait_for_webhook

  _ ->
    :skip
end

# Cancel a pending payout (no params needed)
{:ok, _} = LatticeStripe.Payout.cancel(client, "po_...")

# Cancel with expand for reconciliation
{:ok, payout} =
  LatticeStripe.Payout.cancel(client, "po_...", %{
    "expand" => ["balance_transaction"]
  })

# Reverse a completed payout with reconciliation metadata
{:ok, reversed} =
  LatticeStripe.Payout.reverse(client, "po_...", %{
    "metadata" => %{"reason" => "customer_dispute"},
    "expand" => ["balance_transaction"]
  })

Idempotency

create, cancel, and reverse are money-moving operations. Client.request/2 auto-generates an idempotency key for mutating requests and reuses it across retries. Pass idempotency_key: in opts to set your own stable key.

Stripe API Reference

Summary

Types

t()

A Stripe Payout object.

Types

t()

@type t() :: %LatticeStripe.Payout{
  amount: integer() | nil,
  application_fee: String.t() | nil,
  application_fee_amount: integer() | nil,
  arrival_date: integer() | nil,
  automatic: boolean() | nil,
  balance_transaction: LatticeStripe.BalanceTransaction.t() | String.t() | nil,
  created: integer() | nil,
  currency: String.t() | nil,
  description: String.t() | nil,
  destination:
    LatticeStripe.BankAccount.t() | LatticeStripe.Card.t() | String.t() | nil,
  extra: map(),
  failure_balance_transaction:
    LatticeStripe.BalanceTransaction.t() | String.t() | nil,
  failure_code: String.t() | nil,
  failure_message: String.t() | nil,
  id: String.t() | nil,
  livemode: boolean() | nil,
  metadata: map() | nil,
  method: atom() | String.t() | nil,
  object: String.t(),
  original_payout: String.t() | nil,
  reconciliation_status: String.t() | nil,
  reversed_by: String.t() | nil,
  source_type: String.t() | nil,
  statement_descriptor: String.t() | nil,
  status: atom() | String.t() | nil,
  trace_id: LatticeStripe.Payout.TraceId.t() | nil,
  type: atom() | String.t() | nil
}

A Stripe Payout object.

See the Stripe Payout object for field definitions.

Functions

cancel(client, id, params \\ %{}, opts \\ [])

@spec cancel(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}

Cancels a pending Payout.

Sends POST /v1/payouts/:id/cancel. Only payouts with status: "pending" can be canceled.

Signature (D-03)

cancel(client, id, params \\ %{}, opts \\ []) — the params default is mandatory. Stripe's /cancel endpoint accepts expand, so dropping params would force a breaking change the first time a caller needs expand: ["balance_transaction"].

Example

{:ok, payout} = LatticeStripe.Payout.cancel(client, "po_...")

{:ok, payout} =
  LatticeStripe.Payout.cancel(client, "po_...", %{
    "expand" => ["balance_transaction"]
  })

cancel!(client, id, params \\ %{}, opts \\ [])

@spec cancel!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()

Like cancel/4 but raises LatticeStripe.Error on failure.

create(client, params \\ %{}, opts \\ [])

@spec create(LatticeStripe.Client.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}

Creates a new Payout.

Sends POST /v1/payouts with the given params.

Parameters

  • client — A %LatticeStripe.Client{} struct
  • params — Payout attributes. Stripe requires "amount" and "currency"; LatticeStripe does not pre-validate — Stripe returns a 400 if missing.
  • opts — Per-request overrides (e.g., [idempotency_key: "..."], [stripe_account: "acct_..."])

Example

{:ok, payout} =
  LatticeStripe.Payout.create(client, %{
    "amount" => 5000,
    "currency" => "usd",
    "method" => "instant",
    "source_type" => "card"
  })

create!(client, params \\ %{}, opts \\ [])

@spec create!(LatticeStripe.Client.t(), map(), keyword()) :: t()

Like create/3 but raises LatticeStripe.Error on failure.

from_map(map)

@spec from_map(map() | nil) :: t() | nil

Converts a decoded Stripe API map to a %Payout{} struct.

Maps every known Stripe Payout field explicitly. The nested trace_id map is cast to a typed %LatticeStripe.Payout.TraceId{} struct. Unknown fields land in :extra (F-001).

list(client, params \\ %{}, opts \\ [])

@spec list(LatticeStripe.Client.t(), map(), keyword()) ::
  {:ok, LatticeStripe.Response.t()} | {:error, LatticeStripe.Error.t()}

Lists Payouts with optional filters.

Sends GET /v1/payouts and returns a paginated %Response{data: %List{}} with typed %Payout{} items. All params are optional.

list!(client, params \\ %{}, opts \\ [])

Like list/3 but raises LatticeStripe.Error on failure.

retrieve(client, id, opts \\ [])

@spec retrieve(LatticeStripe.Client.t(), String.t(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}

Retrieves a Payout by ID.

Sends GET /v1/payouts/:id. Raises ArgumentError (pre-network) if id is nil or an empty string.

retrieve!(client, id, opts \\ [])

@spec retrieve!(LatticeStripe.Client.t(), String.t(), keyword()) :: t()

Like retrieve/3 but raises LatticeStripe.Error on failure.

reverse(client, id, params \\ %{}, opts \\ [])

@spec reverse(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}

Reverses a Payout.

Sends POST /v1/payouts/:id/reverse. Only payouts with status: "paid" and type: "bank_account" can be reversed.

Signature (D-03)

reverse(client, id, params \\ %{}, opts \\ []) — the params default is mandatory. Stripe's /reverse endpoint accepts metadata and expand.

Example

{:ok, reversed} =
  LatticeStripe.Payout.reverse(client, "po_...", %{
    "metadata" => %{"reason" => "customer_dispute"},
    "expand" => ["balance_transaction"]
  })

reverse!(client, id, params \\ %{}, opts \\ [])

@spec reverse!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()

Like reverse/4 but raises LatticeStripe.Error on failure.

stream!(client, params \\ %{}, opts \\ [])

@spec stream!(LatticeStripe.Client.t(), map(), keyword()) :: Enumerable.t()

Returns a lazy stream of all Payouts matching the given params.

Emits individual %Payout{} structs, fetching additional pages as needed. Raises LatticeStripe.Error if any page fetch fails.

update(client, id, params, opts \\ [])

@spec update(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}

Updates a Payout by ID.

Sends POST /v1/payouts/:id. Note: Stripe only supports updating metadata on a Payout.

update!(client, id, params, opts \\ [])

@spec update!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()

Like update/4 but raises LatticeStripe.Error on failure.