Packages
Complete Stripe SDK for Elixir with parity to the official Ruby SDK. V1+V2 coverage (193 services, 320 resource structs, 525 documented params). Per-event modules, Finch HTTP/2, RustyJSON, automatic retries, OAuth, webhooks, telemetry, per-client config, streaming pagination.
Current section
Files
Jump to
Current section
Files
lib/stripe/list_object.ex
defmodule Stripe.ListObject do
@moduledoc """
Represents a V1 paginated list response (`object: "list"`).
## Auto-paging
client = Stripe.client("sk_test_...")
{:ok, page} = Stripe.Client.request(client, :get, "/v1/charges")
page
|> Stripe.ListObject.auto_paging_stream(client)
|> Enum.take(50)
"""
alias Stripe.Client
@type t :: %__MODULE__{
object: String.t() | nil,
data: [struct() | map()] | nil,
has_more: boolean() | nil,
url: String.t() | nil
}
defstruct [:object, :data, :has_more, :url]
@doc """
Returns a lazy `Stream` that yields every item across all pages.
Uses `starting_after` cursor pagination. The stream fetches the next page
only when consumed (via `Enum` or `Stream` functions).
"""
@spec auto_paging_stream(t(), Client.t(), keyword()) :: Enumerable.t()
def auto_paging_stream(%__MODULE__{} = page, client, opts \\ []) do
Stream.unfold(page, fn
nil ->
nil
%__MODULE__{data: data, has_more: has_more, url: url} ->
next = if has_more, do: fetch_next_page(client, url, data, opts)
{data, next}
end)
|> Stream.flat_map(& &1)
end
defp fetch_next_page(client, url, data, opts) do
last_id = data |> List.last() |> extract_id()
case Client.request(
client,
:get,
url,
Keyword.merge(opts, params: %{"starting_after" => last_id})
) do
{:ok, %__MODULE__{} = next_page} -> next_page
_ -> nil
end
end
defp extract_id(%{id: id}) when is_binary(id), do: id
defp extract_id(%{"id" => id}) when is_binary(id), do: id
defp extract_id(_), do: nil
end
defmodule Stripe.SearchResult do
@moduledoc """
Represents a V1 search result response (`object: "search_result"`).
## Auto-paging
{:ok, page} = Stripe.Client.request(client, :get, "/v1/charges/search",
params: %{"query" => "status:'succeeded'"})
page
|> Stripe.SearchResult.auto_paging_stream(client)
|> Enum.to_list()
"""
alias Stripe.Client
@type t :: %__MODULE__{
object: String.t() | nil,
data: [struct() | map()] | nil,
has_more: boolean() | nil,
url: String.t() | nil,
next_page: String.t() | nil,
total_count: integer() | nil
}
defstruct [:object, :data, :has_more, :url, :next_page, :total_count]
@doc """
Returns a lazy `Stream` that yields every item across all search result pages.
Uses `page` token pagination (the `next_page` field from each response).
"""
@spec auto_paging_stream(t(), Client.t(), keyword()) :: Enumerable.t()
def auto_paging_stream(%__MODULE__{} = page, client, opts \\ []) do
Stream.unfold(page, fn
nil ->
nil
%__MODULE__{data: data, has_more: has_more, url: url, next_page: next_page_token} ->
next =
if has_more && next_page_token, do: fetch_next_page(client, url, next_page_token, opts)
{data, next}
end)
|> Stream.flat_map(& &1)
end
defp fetch_next_page(client, url, next_page_token, opts) do
case Client.request(
client,
:get,
url,
Keyword.merge(opts, params: %{"page" => next_page_token})
) do
{:ok, %__MODULE__{} = next_page} -> next_page
_ -> nil
end
end
end
defmodule Stripe.V2.ListObject do
@moduledoc """
Represents a V2 paginated list response (detected by `next_page_url` key).
## Auto-paging
{:ok, page} = Stripe.Client.request(client, :get, "/v2/core/events",
api_mode: :v2)
page
|> Stripe.V2.ListObject.auto_paging_stream(client)
|> Enum.take(100)
"""
alias Stripe.Client
@type t :: %__MODULE__{
data: [struct() | map()] | nil,
next_page_url: String.t() | nil
}
defstruct [:data, :next_page_url]
@doc """
Returns a lazy `Stream` that yields every item across all V2 pages.
Uses URL-based pagination — fetches `next_page_url` directly.
"""
@spec auto_paging_stream(t(), Client.t(), keyword()) :: Enumerable.t()
def auto_paging_stream(%__MODULE__{} = page, client, opts \\ []) do
Stream.unfold(page, fn
nil ->
nil
%__MODULE__{data: data, next_page_url: next_url} ->
next = if next_url, do: fetch_next_page(client, next_url, opts)
{data, next}
end)
|> Stream.flat_map(& &1)
end
defp fetch_next_page(client, next_url, opts) do
path = extract_path(next_url, client)
case Client.request(client, :get, path, Keyword.merge(opts, api_mode: :v2)) do
{:ok, %__MODULE__{} = next_page} -> next_page
_ -> nil
end
end
defp extract_path(url, client) do
base = client.api_base
String.replace_prefix(url, base, "")
end
end