Skip to main content

useLemonSqueezyCheckouts

Overview

The use-lemonsqueezy-checkouts.ts module exports a family of hooks and utilities for managing LemonSqueezy checkout data. The primary hook useLemonSqueezyCheckouts provides paginated, filterable checkout listing with full pagination controls and cache management. Additional hooks are provided for single-checkout lookup, POST-based complex queries, and real-time polling. A checkoutUtils object provides client-side data processing helpers.

Source: template/hooks/use-lemonsqueezy-checkouts.ts

Exported Hooks

HookPurpose
useLemonSqueezyCheckoutsPrimary paginated checkout listing with filters
useLemonSqueezyListCheckoutLook up a single checkout by ID from the full list
useLemonSqueezyCheckoutsPostPOST-based mutation for complex filter queries
useLemonSqueezyCheckoutsRealtimeReal-time polling wrapper with configurable interval

useLemonSqueezyCheckouts

The primary hook for fetching and managing LemonSqueezy checkouts.

function useLemonSqueezyCheckouts(
initialFilters?: CheckoutFilters,
options?: UseCheckoutsOptions
): UseCheckoutsReturn

CheckoutFilters

ParameterTypeDefaultDescription
status'active' | 'cancelled' | 'expired' | 'on_trial' | 'past_due' | 'paused' | 'unpaid'undefinedFilter by checkout status
limitnumber100Number of checkouts per page
pagenumber1Page number
customerEmailstringundefinedFilter by customer email
dateFromstringundefinedStart date filter (ISO string)
dateTostringundefinedEnd date filter (ISO string)
storeIdstringundefinedFilter by LemonSqueezy store ID

UseCheckoutsOptions

ParameterTypeDefaultDescription
initialFiltersCheckoutFiltersundefinedOverrides for default filters
enabledbooleantrueWhether the query should execute
refetchIntervalnumberundefinedPolling interval in milliseconds
staleTimenumber300000 (5min)Time before data is considered stale
cacheTimenumber600000 (10min)Time before inactive cache is garbage collected
retryboolean | number3Number of retry attempts on failure
retryDelaynumber1000Delay between retries in milliseconds
onSuccess(data: CheckoutListResponse) => voidundefinedCallback fired on successful fetch
onError(error: Error) => voidundefinedCallback fired on fetch error

Return Values (UseCheckoutsReturn)

Data

PropertyTypeDescription
checkoutsCheckoutData[]Array of checkout records
paginationCheckoutListResponse['pagination'] | nullServer pagination metadata
filtersCheckoutListResponse['filters'] | nullApplied filters from the server
metadataCheckoutListResponse['metadata'] | nullResponse metadata (timestamp, env)

Loading States

PropertyTypeDescription
isLoadingbooleantrue only on initial load
isErrorbooleantrue if the query errored
isFetchingbooleantrue when fetching, including background
isRefetchingbooleantrue when refetching (not initial load)

Error Handling

PropertyTypeDescription
errorError | nullThe error object, if any
errorCodestring | nullError code from the API response

Actions

MethodSignatureDescription
updateFilters(newFilters: Partial<CheckoutFilters>) => voidMerge new filters (resets page to 1)
resetFilters() => voidReset filters to defaults ({ limit: 100, page: 1 })
refresh() => voidRe-execute the current query
invalidateCache() => voidInvalidate all lemonsqueezy/listCheckouts cache keys
nextPage() => voidNavigate to next page (respects hasMore)
prevPage() => voidNavigate to previous page (minimum page 1)
goToPage(page: number) => voidNavigate to a specific page (bounds-checked)

Current State

PropertyTypeDescription
currentFiltersCheckoutFiltersThe currently applied filter state
hasMorebooleanWhether more pages exist
totalPagesnumberTotal number of pages
currentPagenumberCurrent page number
totalnumberTotal number of checkout records

useLemonSqueezyListCheckout

Look up a single checkout by ID from the full checkout list.

function useLemonSqueezyListCheckout(checkoutId: string): {
checkout: CheckoutData | undefined;
isLoading: boolean;
isError: boolean;
error: Error | null;
exists: boolean;
}

Internally fetches up to 100 checkouts and searches for the matching id or checkoutId. The exists property indicates whether the checkout was found.


useLemonSqueezyCheckoutsPost

Mutation-based hook for fetching checkouts via POST (useful for complex filter payloads).

function useLemonSqueezyCheckoutsPost(): {
...UseMutationResult;
fetchCheckouts: (filters: CheckoutFilters) => void;
fetchCheckoutsAsync: (filters: CheckoutFilters) => Promise<CheckoutListResponse>;
}

On success, the result is written into the React Query cache.


useLemonSqueezyCheckoutsRealtime

A convenience wrapper that enables automatic polling at a configurable interval.

function useLemonSqueezyCheckoutsRealtime(
filters?: CheckoutFilters,
interval?: number // default: 30000 (30 seconds)
): UseCheckoutsReturn

Sets staleTime: 0 so data is always considered stale, ensuring every poll returns fresh data.


checkoutUtils

A collection of utility functions for client-side checkout data processing.

MethodSignatureDescription
calculateTotal(checkouts: CheckoutData[], currency?: string) => numberSum amounts for active checkouts by currency
groupByStatus(checkouts: CheckoutData[]) => Record<string, CheckoutData[]>Group checkouts by status
filterByDateRange(checkouts: CheckoutData[], start: Date, end: Date) => CheckoutData[]Filter checkouts within a date range
getUniqueCustomers(checkouts: CheckoutData[]) => string[]Get unique customer email addresses
formatAmount(amount: number, currency?: string) => stringFormat amount as currency string
formatDate(dateString: string, options?: Intl.DateTimeFormatOptions) => stringFormat date with timezone support (UTC)
formatDateShort(dateString: string) => stringShort date format (e.g., "Jan 1, 2025")
formatDateTime(dateString: string) => stringDate with time format
formatDateTimeLocal(dateString: string) => stringDate with time in local timezone
getRawDate(dateString: string) => stringReturn raw date string for debugging
getStats(checkouts: CheckoutData[]) => CheckoutStatsObjectComprehensive stats from checkout array
sortCheckouts(checkouts: CheckoutData[], sortBy?: string, order?: string) => CheckoutData[]Sort by date, amount, status, or email

Implementation Details

  • Query caching: Default 5-minute staleTime and 10-minute gcTime with 3 retries and 1-second retry delay.
  • Filter state: Managed internally via useState. Calling updateFilters merges new values and resets the page to 1.
  • Pagination guards: nextPage, prevPage, and goToPage all perform bounds checking against the server pagination response before updating state.
  • Callbacks: onSuccess and onError callbacks are triggered via useEffect when the query data or error changes.
  • Query key: The query key includes the full filter object, so changing any filter automatically triggers a new query: ['lemonsqueezy', 'listCheckouts', filters].

API Endpoints

OperationMethodEndpoint
List (GET)GET/api/lemonsqueezy/list
List (POST)POST/api/lemonsqueezy/list

Usage Examples

Basic checkout listing with filters

import { useLemonSqueezyCheckouts, checkoutUtils } from '@/hooks/use-lemonsqueezy-checkouts';

function CheckoutsPage() {
const {
checkouts,
isLoading,
totalPages,
currentPage,
total,
updateFilters,
nextPage,
prevPage,
} = useLemonSqueezyCheckouts({ limit: 20 });

if (isLoading) return <Spinner />;

const stats = checkoutUtils.getStats(checkouts);

return (
<div>
<p>{total} checkouts ({stats.active} active)</p>

{/* Status filter */}
<select onChange={(e) => updateFilters({ status: e.target.value as any })}>
<option value="">All</option>
<option value="active">Active</option>
<option value="cancelled">Cancelled</option>
<option value="expired">Expired</option>
</select>

<CheckoutsTable checkouts={checkouts} />

<button onClick={prevPage} disabled={currentPage <= 1}>Previous</button>
<span>Page {currentPage} of {totalPages}</span>
<button onClick={nextPage}>Next</button>
</div>
);
}

Real-time polling for live updates

import { useLemonSqueezyCheckoutsRealtime } from '@/hooks/use-lemonsqueezy-checkouts';

function LiveCheckouts() {
const { checkouts, isFetching } = useLemonSqueezyCheckoutsRealtime(
{ status: 'active' },
10000 // Poll every 10 seconds
);

return (
<div>
{isFetching && <Badge>Updating...</Badge>}
<LiveCheckoutsFeed checkouts={checkouts} />
</div>
);
}

Looking up a single checkout

import { useLemonSqueezyListCheckout } from '@/hooks/use-lemonsqueezy-checkouts';

function CheckoutDetail({ checkoutId }: { checkoutId: string }) {
const { checkout, isLoading, exists } = useLemonSqueezyListCheckout(checkoutId);

if (isLoading) return <Spinner />;
if (!exists) return <NotFound />;

return <CheckoutCard checkout={checkout} />;
}

Using checkout utilities

import { checkoutUtils } from '@/hooks/use-lemonsqueezy-checkouts';

// Format currency
const display = checkoutUtils.formatAmount(49.99, 'USD'); // "$49.99"

// Get stats summary
const stats = checkoutUtils.getStats(checkouts);
console.log(`${stats.uniqueCustomers} unique customers, $${stats.totalAmount} total`);

// Sort by amount descending
const sorted = checkoutUtils.sortCheckouts(checkouts, 'amount', 'desc');