Overview
Pandabase handles the full subscription lifecycle — billing, retries, 3D Secure authentication, invoices, and cancellation. You create a product with type: SUBSCRIPTION, and the platform takes care of everything else.
stateDiagram-v2
[*] --> TRIALING: Customer starts trial
[*] --> ACTIVE: First payment collected
TRIALING --> ACTIVE: Trial ends, payment collected
ACTIVE --> PAUSED: Merchant pauses
PAUSED --> ACTIVE: Merchant resumes
ACTIVE --> PAST_DUE: Payment fails
PAST_DUE --> ACTIVE: Retry succeeds or 3DS completed
PAST_DUE --> CANCELLED: Max retries exhausted
ACTIVE --> CANCELLED: Merchant or customer cancels
TRIALING --> CANCELLED: Cancelled during trialHow it works
- Create a subscription product with a billing interval (weekly, monthly, or yearly)
- Customer checks out — pays the first charge (or starts a free trial)
- Card is saved — Pandabase stores the payment method securely for future charges
- Automatic renewals — the platform charges the customer on each billing cycle
- Invoices sent — customers receive a PDF invoice email on every charge
- Lifecycle events — webhooks fire on every state change
Creating a subscription product
Set type to SUBSCRIPTION and configure the billing interval:
curl -X POST https://api.pandabase.io/v2/core/stores/{storeId}/products \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "title": "Pro Plan", "price": 1999, "type": "SUBSCRIPTION", "billingInterval": "MONTHLY", "status": "ACTIVE", "fulfillmentMode": "MANUAL" }'| Field | Options | Description |
|---|---|---|
billingInterval |
WEEKLY, MONTHLY, YEARLY |
How often the customer is charged |
trialDays |
0–365 |
Free trial period before first charge (optional) |
Checkout flow
Create a checkout session with a subscription product — the checkout UI automatically adapts:
- Shows the billing interval (e.g. “$19.99 / month”)
- Shows trial info if applicable (e.g. “7-day free trial, then $19.99/month”)
- Restricts payment to card and Link (required for recurring billing)
- Shows a consent checkbox before payment
- Button text changes to “Subscribe” or “Start subscription”
curl -X POST https://api.pandabase.io/v2/stores/{storeId}/checkouts \ -H "Content-Type: application/json" \ -d '{ "items": [{ "product_id": "prd_xxx", "quantity": 1 }], "customer": { "name": "Jane Doe", "email": "jane@example.com", "billing": { "line1": "123 Main St", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country": "US" } } }'Subscription statuses
| Status | Description |
|---|---|
TRIALING |
Customer is in a free trial — no charges until trial ends |
ACTIVE |
Billing is active, customer is being charged on schedule |
PAST_DUE |
Payment failed — retrying automatically or awaiting 3DS verification |
PAUSED |
Billing paused by merchant — no charges until resumed |
CANCELLED |
Subscription ended — no further charges |
Free trials
Set trial_days on the product to offer a free trial:
{ "title": "Pro Plan", "price": 1999, "type": "SUBSCRIPTION", "billingInterval": "MONTHLY", "trialDays": 7, "status": "ACTIVE"}During checkout, the customer saves their card without being charged. The subscription starts in TRIALING status and the first charge happens automatically when the trial ends.
Failed payments and retries
When a renewal payment fails, Pandabase:
- Moves the subscription to
PAST_DUE - Fires a
SUBSCRIPTION_PAST_DUEwebhook - Emails the customer about the failed payment
- Retries automatically with backoff:
- Retry 1: 24 hours later
- Retry 2: 48 hours later
- Retry 3: 72 hours later
- If all retries fail, the subscription is cancelled
3D Secure on renewals
Some banks require 3D Secure authentication for recurring charges. When this happens:
- The subscription moves to
PAST_DUE - The customer receives an email with a secure verification link
- The customer clicks the link and completes the bank’s authentication
- The payment is processed and the subscription returns to
ACTIVE
No action is needed from you — Pandabase handles the authentication flow automatically.
Managing subscriptions
Via API
Use SUBSCRIPTIONS_READ and SUBSCRIPTIONS_WRITE permissions on your API token:
# list subscriptionsGET /v2/core/stores/{storeId}/subscriptions# get subscription detailGET /v2/core/stores/{storeId}/subscriptions/{subscriptionId}# cancel (at period end by default)POST /v2/core/stores/{storeId}/subscriptions/{subscriptionId}/cancel# cancel immediatelyPOST /v2/core/stores/{storeId}/subscriptions/{subscriptionId}/cancel -d '{ "immediate": true }'# pause billingPOST /v2/core/stores/{storeId}/subscriptions/{subscriptionId}/pause# resume billingPOST /v2/core/stores/{storeId}/subscriptions/{subscriptionId}/resumeVia Customer Portal
Customers can view and cancel their subscriptions at mypandabase.com. Cancellation is always at period end — customers retain access until the current billing period expires.
Cancellation behavior
| Who cancels | Behavior |
|---|---|
| Merchant (default) | Cancels at end of current billing period |
| Merchant (immediate) | Cancels immediately, revokes access, revokes licenses if revoke_on_refund is enabled |
| Customer | Always cancels at end of current billing period |
| System (max retries) | Cancels after 4 failed payment attempts |
Webhook events
Six events are available for subscription state changes:
| Event | When |
|---|---|
SUBSCRIPTION_CREATED |
First payment or trial setup succeeds |
SUBSCRIPTION_RENEWED |
Renewal payment succeeds |
SUBSCRIPTION_PAST_DUE |
Renewal failed or needs 3DS |
SUBSCRIPTION_CANCELLED |
Cancelled by merchant, customer, or max retries |
SUBSCRIPTION_PAUSED |
Merchant paused billing |
SUBSCRIPTION_RESUMED |
Merchant resumed billing |
See Webhook Events for payload details and integration examples.
Invoices
Customers automatically receive a PDF invoice via email on:
- The first subscription payment
- Every renewal payment
Invoices include the product name, amount, billing period, tax breakdown, and next charge date.
Usage-based billing
If you need to charge per request, per token, per seat, or any other metric where the bill is not known in advance, configure the product with pricingModel: USAGE_BASED and attach meters. The lifecycle, retries, invoices, and webhook events described on this page apply unchanged. See Usage-based billing for the meter model, event ingestion, and renewal math.
Limitations
- Only one subscription item per checkout (no mixing with one-time items)
- Billing is in USD only (multicurrency renewals are a future enhancement)
- Price is locked at creation — changing the product price does not affect existing subscriptions
- Subscription upgrades/downgrades are not yet supported — cancel and re-subscribe