Skip to main content

Memberships

A membership is a pass that charges every month and gives its holder a discount. Create one with POST /passes and billing: "monthly":

  • the price is the monthly fee, in the shop's currency;
  • discount_percent (1 to 100) comes off every line the membership covers, for everyone on the booking;
  • it has no visits and no dates: it works while it is paid.

The first month is paid when the membership is bought (on the booking page, in POS, or on a booking sent to POST /bookings with passes). The card is kept and Stripe charges it on the same day each month. Members keep the price and discount they signed up at, even if the pass changes later.

Needs Stripe

A monthly fee is a Stripe subscription on the shop's own Stripe account. A shop that does not take card payments through Stripe, or whose Stripe account cannot take charges yet, gets 422 memberships_need_stripe when it creates a monthly pass or switches a pass to monthly.

A membership a customer holdsโ€‹

A membership shows up in GET /customer-passes like any other pass, with billing: "monthly" and these fields filled in:

{
"id": 57,
"pass_id": 9,
"customer_id": 208,
"holder_name": "Jane Doe",
"code": "MEMBER-4HQZ-8KDW",
"name": "Members Club",
"status": "active",
"billing": "monthly",
"discount_percent": 15.0,
"paid_through": "2026-08-09",
"renews_on": "2026-08-10",
"cancel_at": null,
"ended_at": null,
"status_label": "Active - renews Aug 10, 2026 - $20.00 a month",
"price": 20.0,
"currency": "USD"
}
FieldDescription
paid_throughThe last day of the month already paid for, in the shop's time zone
renews_onThe day the next monthly charge is taken. null once it is cancelled or has ended
cancel_atSet when it was cancelled to run to the end of the paid month: the last day it works
ended_atWhen it stopped for good
status_labelThe same line the shop sees on the membership's page
statusMeaning
pendingBought, first month not paid yet
activePaid up. The discount works
payment_dueA monthly charge failed. The discount keeps working to paid_through, then stops until it is paid. Stripe retries for about a week
endedCancelled and past its paid month, or Stripe gave up on the payment. The discount no longer works

Cancel a membershipโ€‹

POST /v1/customer-passes/{id}/cancel

Scope store:write.

FieldTypeRequiredDescription
nowbooleannoDefault false: it keeps working to the end of the month already paid for, then stops. true ends it today

Either way it is not charged again. Returns 200 with the membership. A membership that is already cancelled or has ended returns 422 membership_not_cancelled; a season pass returns 404.

List the monthly chargesโ€‹

GET /v1/customer-passes/{id}/payments

Scope store:read. Every monthly charge on a membership, newest first.

{
"data": [
{
"id": 311,
"customer_pass_id": 57,
"status": "paid",
"amount": 20.0,
"processing_fee": 0.0,
"refunded_amount": 0.0,
"stripe_fee": 0.88,
"stripe_fee_tax": null,
"platform_fee": 0.20,
"payout_id": "po_1Nexample",
"net_amount": 20.0,
"currency": "usd",
"period_start": "2026-07-10",
"period_end": "2026-08-09",
"receipt_url": "https://invoice.stripe.com/i/acct_example/test_example",
"paid_at": "2026-07-10T16:00:04+00:00",
"created_at": "2026-07-10T16:00:04+00:00"
}
]
}

status is paid, failed or refunded. net_amount is what the shop kept: the amount less anything refunded, and 0 for a failed charge. processing_fee is the card fee inside amount when the shop passes processing fees on to its customers, and 0 otherwise.

stripe_fee is the fee Stripe took on the charge, stripe_fee_tax the tax Stripe charged on that fee (where it charges one), platform_fee the EquipDash fee, and payout_id the Stripe payout the charge went out in. All four are null until Stripe has settled the charge. The membership.renewed and membership.payment_failed webhooks send the same fields.

Put the member discount on a bookingโ€‹

POST /v1/bookings/{id}/membership

Scope bookings:write. The same check the booking page and POS use.

FieldTypeRequiredDescription
codestringyesThe membership code

The discount comes off every line the membership covers. A membership and a promo code do not combine: if the booking already has a promo code that takes more off, the promo code stays and the call returns 422; if the membership takes more off, it replaces the promo code.

{
"data": {
"discount": 12.0,
"discount_percent": 15.0,
"replaced_promo_code": false,
"booking_total": 68.0,
"membership": { "id": 57, "code": "MEMBER-4HQZ-8KDW", "status": "active" }
}
}

Returns 201. When the code does not work the call returns 422 membership_not_applied and error.message says why, for example "This membership has a payment due." Whether a membership works is judged on the day the booking is made, so a paid-up member can book months ahead.

Take the member discount offโ€‹

DELETE /v1/bookings/{id}/membership

Scope bookings:write. Returns 204, or 404 when the booking has no member discount.

Webhooksโ€‹

EventWhendata
membership.renewedA monthly charge is paid (a new month, or a failed charge paid later)The charge, as in the list above, with its membership
membership.payment_failedA monthly charge failsThe charge, with its membership
membership.cancelledA membership is cancelled (cancel_at set, still working to the end of the paid month), and again when it stops (status: "ended")The membership

See Webhook events.