Skip to main content
This page is the end-to-end integration path for subscriptions: create a checkout for a subscription offer, list your subscribers, gate access on a subscriber’s live status, cancel/pause/resume from your backend, and react to subscription webhooks. You can create offers through the REST API or in the dashboard — see the subscriptions guide. For the full endpoint catalog, see the API reference.
1

Sell

POST /checkout/sessions with your subscription offer’s id, redirect the buyer to the returned url.
2

Gate

Check GET /subscriptions/subscribers/{id} (optionally ?live=true) before serving paid content.
3

React

Verify and handle customer.subscription.* / invoice.* webhooks to keep your records in sync.

1. Authentication and base URL

Every request goes to https://api.pocketsflow.com with your API key in the Authorization header — pk_live_… for live mode, pk_test_… for sandbox data. Create keys in the dashboard under Developers → API keys, and keep them server-side only. Details: Authentication & security.

Create a subscription offer

Use POST /subscriptions to create the recurring product before creating a checkout session. The endpoint accepts JSON for API clients and multipart/form-data when you also need to upload offer assets.
cURL
price is in USD. frequency must be weekly, monthly, or yearly; trialPeriod is the number of trial days. The endpoint returns the created offer with 201 Created. The same operation is available through the official Node.js/TypeScript SDK:
Install the SDK with npm install pocketsflow. See the SDK guide for configuration, resource methods, and error handling. The SDK source’s current v1.2.0 release includes subscriptionOffers.create; if your installed npm version predates that release, use the REST request above until you upgrade.

2. Create a checkout session for a subscription offer

POST /checkout/sessions accepts a subscription offer id in productId (the same field used for one-time products — pass either kind of id). Redirect the buyer to the url in the response; Pocketsflow hosts the checkout and the recurring billing.
The response is 201 with:
successUrl/cancelUrl must be absolute http(s) URLs; clientReferenceId (max 256 chars) and metadata are captured at activation and replayed on every customer.subscription.* / invoice.* webhook, so you can bind events back to your own user records. The full field table is in the custom platforms guide.

3. List your subscription offers

GET /subscriptions returns your offers (the recurring products), newest first, scoped to your account and the key’s test/live mode. Use it to find the _id to sell in step 2.
frequency is weekly, monthly, or yearly. A single offer is available at GET /subscriptions/{id} (404 if it doesn’t exist or isn’t yours).

4. List subscribers (filter by status)

GET /subscriptions/subscribers is the paginated roster of buyers across your offers. Filters: status, buyerEmail (alias email), subscriptionId, page (default 1), pageSize (default 20).
status values include active, trialing, past_due, paused, and canceled (full list in the API reference). portalUrl is the subscriber’s self-service portal — share it so buyers can manage their own membership.

5. Verify one subscriber’s live status (the access gate)

Before serving paid content, look the subscriber up by their _id (the 24-hex Mongo id from step 4 or from webhooks — not a mem_… id here). Add ?live=true to also fetch the authoritative membership from the payment processor as whopMembership; if that live lookup fails, whopMembership is null and the stored status still applies, so the request never fails.
payments is the full history for this membership — the initial charge plus every renewal. For hot paths, gate on the stored status (kept fresh by webhooks) and reserve ?live=true for the moments that matter, like restoring account access after a failed payment.

6. Cancel, pause, or resume a subscriber

Three lifecycle actions, all POST with an empty body. {id} is the subscriber’s _id or their processor membership id (mem_…).
cancel and resume respond with:
pause adds a paused boolean to the same shape. Pause is provider-first: if the processor refuses, you get a 502 and no local state changes — and a subscriber with no membership on record returns 400. Cancelling also fires the customer.subscription.updated webhook (and customer.subscription.deleted when the membership actually ends); pausing/resuming fire customer.subscription.pause / customer.subscription.resumed.

7. Receive and verify subscription webhooks

Register an endpoint (dashboard, or POST /webhooks) and subscribe to the subscription events. Every delivery is a POST with these headers: Subscription-related events: customer.subscription.created, customer.subscription.updated, customer.subscription.deleted, customer.subscription.pause, customer.subscription.resumed, customer.subscription.trial_will_end, invoice.created, invoice.upcoming, invoice.payment_succeeded, invoice.payment_failed, payment_intent.succeeded, and payment_intent.payment_failed. Every payload carries a top-level subscriptionCustomerId (the subscriber _id from steps 4–6) and your clientReferenceId/metadata from checkout. Payload shapes: Webhook events. Always verify the signature over the raw body (never re-serialize the parsed JSON) with a constant-time comparison:
Each event is delivered with a single attempt and a 5-second timeout — acknowledge with a 2xx immediately and do the real work asynchronously. If a delivery is missed, reconcile via GET /subscriptions/subscribers (step 4).

Example repository

Prefer runnable code? The subscriptions example on GitHub has everything on this page as a clone-and-run project: a checkout embed (hosted link, popup, and inline) plus a Node/Express webhook receiver that verifies the signature and handles the full subscription lifecycle.