Use Case: Public Membership Info
Memberships API vs Membership Signup Page
The membership signup page and GET /apis/v2/memberships share the same backend data, but the page applies location or slug filters, active/listed rules, and billing tabs in the browser — and it groups products by membership plan instead of listing every Membership as its own card. An unfiltered API call from an admin key will return more results than what a Customer sees on the signup page.
Why the API key is not the end user
The API key runs as whichever admin user it was created for — not as an anonymous or logged-in Customer on the website. That means an admin key can return:
Unlisted ("hidden") Memberships when using
includeUnlisted=trueInactive Memberships when using
status=INACTIVEUnlisted one-time price options inside
expand=items._links.oneTimePriceOptionswhen the API user has manage permissions
Do not compare an unfiltered GET /memberships (no query parameters) from an admin API key to the public Membership page.
Step 1 — Request with explicit filters
Call GET /memberships with the following query parameters to match what the signup page shows:
status
ACTIVE
Excludes archived Memberships; same as the public page
areaId
<area-id>
Matches a location on the website. Resolve the slug via GET /apis/v2/areas first — the id is often the same as the slug (e.g. les) but always confirm
ipp
200
The web client loads many plans; the API default page size is 30. Paginate if _total exceeds ipp
expand
items._links.areas and items._links.oneTimePriceOptions
Same expansions the web client uses
includeUnlisted
Omit
Parity with the public listed catalog
slug
<membership-slug>
Only when mirroring a direct membership link (bypasses the listed filter for that slug)
Example: resolve area, then list Memberships
Step 1 — List areas (replace TENANT and <API_KEY>):
Step 2 — List Memberships (website-aligned):
Note for franchise / area-scoped API keys: If the key is restricted to certain locations, always pass
areaIdexplicitly. Omitting it may return Memberships for all areas that key's user can manage — broader than a singlelocation=on the web.
Step 2 — Match the URL pattern
Installations differ. Match the API call to the URL pattern the Customer actually uses.
Pattern A — Location and region (multi-location picker)
Used when the tenant enables location filtering (feature.membershipLocationFilter). The URL carries slugs:
Optional chargeType URL parameters select the billing tab in the UI (MONTHLY, YEARLY, NON_RECURRING).
Important:
chargeTypevalues are applied in the browser only. They are not sent toGET /memberships. Filter byallowedChargeTypeson the response instead — see Filter by charge type below.
Matching API call:
Method:
GET /apis/v2/membershipsQuery:
status=ACTIVE,areaId=les,ipp=200, plus bothexpandparametersUse
areaId(the area'sidforles), notregion
Pattern B — Membership slug (direct product link)
Used for a specific Membership landing page (common on newer setups):
The Customer is not always asked to pick region/location first; the Membership itself defines the offer and areas.
Matching API call:
Query:
slug=home-astoria,expand=items._links.areas,expand=items._links.oneTimePriceOptionsUsing
slug=can return a plan even if it is unlisted on the public grid — same behavior as a "hidden" direct link
Summary: areaId= mirrors the location picker catalog. slug= mirrors a direct Membership URL.
Step 3 — Match the frontend grouping
The API returns a flat items[] array (one object per Membership). The website groups and filters that list in JavaScript.
Memberships vs membership plans
Membership — The sellable product: price, areas, benefits, slug. Examples:
BASIC_NYC("New York"),GLOBAL("Global").Membership plan — A group label stored on each Membership (
membershipPlan.id,membershipPlan.displayName). Several Memberships can share one plan.
Example: BASIC_NYC and BASIC_NYC_NJ both belong to the plan PingPod Access (BASIC_MEMBER). The website shows one card titled "PingPod Access" with a dropdown to choose between them — not two separate cards.
Group items by membershipPlan.id (or membershipPlan.displayName). Each group corresponds to one card on the signup page. Multiple Memberships in the same group appear as options in a dropdown on that card.
Filter by charge type
Billing tabs are not API query parameters. Filter the items array in code after you receive the response:
Monthly
allowedChargeTypes includes "MONTHLY"
Yearly
allowedChargeTypes includes "YEARLY"
One-time
allowedChargeTypes includes "NON_RECURRING". For display parity with the UI, prefer oneTimePriceOptions entries where listed is true
A Membership with ["MONTHLY", "NON_RECURRING"] can appear on both the Monthly and One-time tabs depending on the selected tab.
Common questions
Why does the API list more Memberships than the website? The API key is running as an admin — it may have includeUnlisted=true, no status or areaId filter, or a franchise key without an explicit location. Also: the API returns flat items while the website shows grouped plan cards.
Why is Global visible but not "New York"? Global often has its own plan card ("PingPod Fanatics"). "New York" is usually inside the "PingPod Access" card as a dropdown option, not a separate top-level card.
Why does the API include New York on Monthly but not on One-time? BASIC_NYC is typically monthly-only (allowedChargeTypes: ["MONTHLY"]). Filter by tab after the GET.
What is the difference between ?location=les and ?membership=home-astoria? location / region drives the regional catalog — use areaId= in the API. membership / path slug is a direct product link — use slug= in the API.
Integrator checklist
Call
GET /membershipswithstatus=ACTIVE,areaIdorslug,ipp=200, and bothexpandparameters.Do not use
includeUnlisted=truewhen comparing to the public signup page.Remember the API key user may see more than an end Customer.
Group results by
membershipPlan.id.Filter by
allowedChargeTypesfor Monthly, Yearly, or One-time tabs.Use
slug=only for direct Membership URLs; useareaId=for location-picker flows.
API reference
Base path:
/apis/v2/Auth header:
x-api-key: <API_KEY>List Memberships:
GET /membershipsList areas:
GET /areas
Last updated
Was this helpful?

