Paginated API response with cursor-based navigation.
Supports eager fetching (list one page) and lazy streaming
(process all pages via Stream).
WhatsApp Pagination Format
The WhatsApp Cloud API uses cursor-based pagination:
%{
"data" => [...],
"paging" => %{
"cursors" => %{"before" => "QVFIUl...", "after" => "QVFIUk..."},
"next" => "https://graph.facebook.com/v23.0/.../message_templates?after=QVFIUk...",
"previous" => "https://graph.facebook.com/v23.0/.../message_templates?before=QVFIUl..."
}
}Usage
# Parse a response into a Page
page = WhatsApp.Page.from_response(response_body, &deserialize/1)
# Check for more pages
WhatsApp.Page.has_next?(page)
# Stream all items across all pages lazily
page
|> WhatsApp.Page.stream(client)
|> Stream.filter(&active?/1)
|> Enum.to_list()
Summary
Functions
Parse a paginated API response into a Page struct.
Returns true if the page has a next page URL.
Returns true if the page has a previous page URL.
Create a lazy stream that auto-pages through all items.
Types
Functions
Parse a paginated API response into a Page struct.
response_map is the decoded JSON map with "data" and "paging" keys.
deserialize_fn is a function that transforms each data item. Pass nil
to keep raw maps.
Examples
iex> response = %{"data" => [%{"id" => "1"}], "paging" => %{"cursors" => %{"after" => "abc"}}}
iex> page = WhatsApp.Page.from_response(response, nil)
iex> page.data
[%{"id" => "1"}]
Returns true if the page has a next page URL.
Examples
iex> WhatsApp.Page.has_next?(%WhatsApp.Page{next_url: "https://..."})
true
iex> WhatsApp.Page.has_next?(%WhatsApp.Page{next_url: nil})
false
Returns true if the page has a previous page URL.
Examples
iex> WhatsApp.Page.has_previous?(%WhatsApp.Page{previous_url: "https://..."})
true
iex> WhatsApp.Page.has_previous?(%WhatsApp.Page{previous_url: nil})
false
@spec stream(t(), WhatsApp.Client.t() | nil, keyword()) :: Enumerable.t()
Create a lazy stream that auto-pages through all items.
Uses Stream.unfold/2 to yield individual items from the current page,
then automatically fetches the next page when data is exhausted.
The stream stops when there are no more pages or on fetch error.
Options
:deserialize_fn- Function to apply to items from fetched pages. Items from the initial page are yielded as-is (already deserialized byfrom_response/2).:fetch_fn- Custom fetch function(client, url) -> {:ok, map()} | {:error, term()}. Defaults toWhatsApp.Client.request_url/2. Useful for testing.
Examples
# Stream all templates across all pages
page
|> WhatsApp.Page.stream(client, deserialize_fn: &deserialize/1)
|> Enum.to_list()
# Take only the first 50 items (lazy — fetches only needed pages)
page
|> WhatsApp.Page.stream(client)
|> Enum.take(50)