For the complete documentation index, see llms.txt. This page is also available as Markdown.

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=true

  • Inactive Memberships when using status=INACTIVE

  • Unlisted one-time price options inside expand=items._links.oneTimePriceOptions when 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:

Parameter
Value
Purpose

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 areaId explicitly. Omitting it may return Memberships for all areas that key's user can manage — broader than a single location= 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: chargeType values are applied in the browser only. They are not sent to GET /memberships. Filter by allowedChargeTypes on the response instead — see Filter by charge type below.

Matching API call:

  • Method: GET /apis/v2/memberships

  • Query: status=ACTIVE, areaId=les, ipp=200, plus both expand parameters

  • Use areaId (the area's id for les), not region

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.oneTimePriceOptions

  • Using 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:

Tab
Filter

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.

Example API response and how it maps to the website (LES, Monthly tab)

Illustrative payload for GET .../memberships?status=ACTIVE&areaId=les&ipp=200&expand=... (fields shortened):

How this maps to the website (LES, Monthly tab):

  • GLOBAL → one card: PingPod Fanatics (standalone)

  • BASIC_NYC + BASIC_NYC_NJ → one card: PingPod Access, with a dropdown ("New York", "New York + New Jersey")

  • membership-pricing-test → card Test; also visible on the One-time tab

"New York" appears on the site under PingPod Access, not as its own top-level card next to Global.

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

  1. Call GET /memberships with status=ACTIVE, areaId or slug, ipp=200, and both expand parameters.

  2. Do not use includeUnlisted=true when comparing to the public signup page.

  3. Remember the API key user may see more than an end Customer.

  4. Group results by membershipPlan.id.

  5. Filter by allowedChargeTypes for Monthly, Yearly, or One-time tabs.

  6. Use slug= only for direct Membership URLs; use areaId= for location-picker flows.

API reference

  • Base path: /apis/v2/

  • Auth header: x-api-key: <API_KEY>

  • List Memberships: GET /memberships

  • List areas: GET /areas

Last updated

Was this helpful?