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. Send it exactly as returned: its ?token=… is what lets the buyer cancel or resume. A link you build yourself from the two ids (without the token) opens the portal read-only.

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 membership; if that live lookup fails, membership 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: Every body also carries top-level id, type, and created (Unix seconds), plus test: true on deliveries sent with POST /webhooks/{id}/test. 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. The examples below check the legacy X-Pocketsflow-Signature; to use X-Pocketsflow-Signature-V2, compute the same HMAC over `${t}.${rawBody}` and compare it to the v1 value — see Authentication & security.
Each attempt has a 5-second timeout — acknowledge with a 2xx immediately and do the real work asynchronously. A delivery that gets a 5xx or a 429, or never reaches your endpoint, is retried (up to 3 attempts, about 1 s and 4 s apart) with the same event id; a timeout is not retried. Every attempt is in the delivery log (GET /delivered-webhooks, kept 30 days) and can be replayed with POST /delivered-webhooks/{id}/redeliver; you can also 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.