Pular para o conteúdo

Memberships

Este conteúdo não está disponível em sua língua ainda.

Memberships are recurring customer plans, a monthly or yearly subscription that can carry benefits like a shop-wide discount, included services per billing cycle, and priority handling. The API exposes the plan catalog, customer enrollments, a fast live-membership lookup (the same check the in-app checkout badge uses), and a way to mint a plan’s public signup link.

This resource is read-first by design: the money paths, enroll, charge, cancel, pause, card vaulting, are deliberately not exposed on the public API. The only write is the signup-link mint, which is inert: it returns the same public self-serve signup URL the staff UI shares.

{
"object": "membership_plan",
"id": 4,
"name": "Priority Care",
"description": "Priority bench time and 10% off repairs.",
"amount": { "amount_cents": 1999, "amount": "19.99", "currency": "USD" },
"billing_interval": "month",
"benefits": {
"discount_pct": 10,
"included_services": [
{ "name": "Screen protector install", "qty": 1 }
],
"priority": true
},
"active": true,
"created_at": "2026-04-02T15:00:00.000Z",
"updated_at": "2026-06-20T10:12:00.000Z"
}
FieldTypeDescription
idintegerUnique plan ID
namestringPlan name
descriptionstring|nullPlan description
amountmoneyThe recurring price per billing interval
billing_intervalstringmonth or year
benefitsobject|nullThe plan’s benefits definition, when one is configured (see below)
activebooleanfalse = archived (closed to new enrollments)
created_atstring|nullISO-8601 creation timestamp
updated_atstring|nullISO-8601 last-updated timestamp
FieldTypeDescription
discount_pctnumber|nullShop-wide discount percent, 0–100
included_servicesarray{ name, qty } pairs, included uses per billing cycle
prioritybooleanMembers get priority handling

An enrollment of one customer in one plan.

{
"object": "membership",
"id": 118,
"plan_id": 4,
"plan_name": "Priority Care",
"customer_email": "jane.smith@example.com",
"customer_name": "Jane Smith",
"customer_phone": "555-867-5309",
"status": "active",
"started_at": "2026-05-01T14:00:00.000Z",
"next_charge_at": "2026-08-01T14:00:00.000Z",
"cancel_at_period_end": false,
"canceled_at": null
}
FieldTypeDescription
idintegerUnique enrollment ID
plan_idintegerThe plan enrolled in
plan_namestring|nullDenormalized plan name
customer_emailstring|nullCustomer’s email
customer_namestring|nullCustomer’s name
customer_phonestring|nullCustomer’s phone
statusstringactive, paused, canceled, past_due, pending_signature, or expired
started_atstring|nullISO-8601 enrollment start
next_charge_atstring|nullThe next billing-cycle boundary (the current period’s end)
cancel_at_period_endbooleantrue when a cancel is scheduled for the cycle boundary
canceled_atstring|nullISO-8601 cancellation timestamp

GET /api/v1/memberships/plans

Returns the plan catalog, cursor-paginated. Archived plans are hidden by default; pass include_archived=true to include them.

Scope required: memberships.read

ParameterTypeDescription
include_archivedbooleanInclude archived (inactive) plans (default: false)
limitintegerPage size, 1–100 (default: 25)
cursorstringOpaque cursor from a previous response’s next_cursor
Terminal window
curl "https://app.benchkey.com/api/v1/memberships/plans" \
-H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"
{
"object": "list",
"data": [ { "object": "membership_plan", "id": 4, "name": "Priority Care" } ],
"has_more": false,
"next_cursor": null
}

Additional resource fields are omitted from this example.


GET /api/v1/memberships/plans/:plan_id

Returns a single plan.

Scope required: memberships.read

Terminal window
curl "https://app.benchkey.com/api/v1/memberships/plans/4" \
-H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"

Returns the membership plan object. Returns 404 if no plan with that ID exists.


GET /api/v1/memberships

Returns a cursor-paginated list of customer plan enrollments, newest first. Filter by customer email, plan, or status.

Scope required: memberships.read

ParameterTypeDescription
customerstringFilter to one customer’s memberships by email (exact, case-insensitive)
plan_idintegerFilter to enrollments of one plan
statusstringFilter by status: active, paused, canceled, past_due, pending_signature, expired
limitintegerPage size, 1–100 (default: 25)
cursorstringOpaque cursor from a previous response’s next_cursor
Terminal window
curl "https://app.benchkey.com/api/v1/memberships?status=active&limit=10" \
-H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"
const res = await fetch(
"https://app.benchkey.com/api/v1/memberships?status=active&limit=10",
{ headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" } }
);
const { data, has_more, next_cursor } = await res.json();
{
"object": "list",
"data": [ { "object": "membership", "id": 118, "status": "active" } ],
"has_more": false,
"next_cursor": null
}

Additional resource fields are omitted from this example.

See Pagination for how to page through results.


GET /api/v1/memberships/:id

Returns one customer plan enrollment by ID.

Scope required: memberships.read

Terminal window
curl "https://app.benchkey.com/api/v1/memberships/118" \
-H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"

Returns the membership object. Returns 404 if no membership with that ID exists.


GET /api/v1/memberships/lookup

Answers “is this customer a live member?” for one email. Mirrors the in-app checkout badge: only live statuses (active, past_due, paused) count, and when a customer holds several live enrollments the healthiest one wins (active over past_due over paused).

Scope required: memberships.read

ParameterRequiredTypeDescription
customeryesstringThe customer’s email address
Terminal window
curl "https://app.benchkey.com/api/v1/memberships/lookup?customer=jane.smith@example.com" \
-H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"
{
"object": "membership_lookup",
"customer_email": "jane.smith@example.com",
"member": true,
"status": "active",
"plan_name": "Priority Care"
}
FieldTypeDescription
customer_emailstringThe email queried
memberbooleantrue when the customer has a live membership
statusstring|nullactive, past_due, or paused, null when member is false
plan_namestring|nullThe live plan’s name, or null

POST /api/v1/memberships/plans/:plan_id/signup-link

Mints (or returns, a plan keeps its token forever, so links in the wild never rot) the plan’s public self-serve signup URL. Idempotent: repeated calls return the same link.

Scope required: memberships.write

Terminal window
curl -X POST "https://app.benchkey.com/api/v1/memberships/plans/4/signup-link" \
-H "Authorization: Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa"
const res = await fetch(
"https://app.benchkey.com/api/v1/memberships/plans/4/signup-link",
{
method: "POST",
headers: { Authorization: "Bearer bk_live_01J8X4_kvWz9nP3mRqTs7uYeBfGhDjLa" },
}
);
const { url } = await res.json();
{
"object": "membership_signup_link",
"plan_id": 4,
"token": "3f2a9c81d4e07b5a6c9d2e8f1a0b3c4d5e6f7a8b9c0d1e2f",
"url": "https://app.benchkey.com/plan-signup/3f2a9c81d4e07b5a6c9d2e8f1a0b3c4d5e6f7a8b9c0d1e2f"
}
FieldTypeDescription
plan_idintegerThe plan the link signs customers up for
tokenstringThe public signup token (stable for the plan’s lifetime)
urlstringThe public self-serve signup URL to share

HTTP statusCodeMeaning
400invalid_queryA query parameter was supplied as an array or object instead of a single scalar value, or an invalid status/plan_id filter
400invalid_cursorThe pagination cursor is malformed
400missing_fieldThe required customer query parameter is absent on lookup
404not_foundNo membership or membership plan with that ID exists for this tenant
422create_failedThe signup link could not be minted
403insufficient_scopeAPI key lacks memberships.read or memberships.write

See Errors for the full error envelope format.

Status do sistema