Quickstart: Create a subscription with Checkout
Use this quickstart to create the beginner subscription path: a customer chooses a plan, completes Checkout, and your backend grants access from confirmed server-side billing events.
What you will build
You will:
- Create or select a recurring Price.
- Create a Checkout Session in
subscriptionmode. - Send the customer to Checkout.
- Handle server-side events.
- Store the IDs needed for future renewals and support.
- Grant or extend access from invoice events.
Before you start
You need:
- Paypercut API keys.
- An internal user, account, workspace, or tenant that will receive access.
- A Product and recurring Price for the plan.
- A webhook endpoint that verifies Paypercut signatures.
For pricing setup, see Products and Prices. For webhook signatures, see Webhook Signature Verification.
If you are starting from an empty test account, create the customer, product, and recurring price first. Keep the returned IDs and use them in the Checkout Session request.
curl https://api.paypercut.io/v1/customers \
-X POST \
-H "Authorization: Bearer $PAYPERCUT_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: subscription-customer-01" \
-d '{
"email": "customer@example.com",
"name": "Example Customer"
}'
curl https://api.paypercut.io/v1/products \
-X POST \
-H "Authorization: Bearer $PAYPERCUT_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: subscription-product-01" \
-d '{
"name": "Pro plan"
}'
curl https://api.paypercut.io/v1/prices \
-X POST \
-H "Authorization: Bearer $PAYPERCUT_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: subscription-price-01" \
-d '{
"product": "01HPRODUCT000000000000000",
"type": "recurring",
"currency": "EUR",
"unit_amount": 1900,
"recurring": {
"interval": "monthly",
"interval_count": 1,
"usage_type": "licensed"
}
}'
Flow overview
| Step | Actor | Action |
|---|---|---|
| 1 | Your backend | Creates a Checkout Session in subscription mode. |
| 2 | Your frontend | Redirects or embeds the Checkout Session. |
| 3 | Customer | Completes Checkout. |
| 4 | Paypercut | Creates the subscription flow and sends server-side events. |
| 5 | Your backend | Stores IDs and processes checkout_session.completed, invoice.paid, and invoice.payment_failed. |
| 6 | Your backend | Grants, extends, or recovers access from confirmed state. |
Step 1: Create or select a recurring Price
Subscription Checkout line items must use recurring pricing. Use a catalog Price for plans you sell repeatedly.
Store the price_id with your internal plan, such as:
| Internal plan | Paypercut Price |
|---|---|
pro_monthly |
01HFRECURRINGPRICE000000000 |
Do not use a one-time Price for a subscription Checkout Session.
Step 2: Create a Checkout Session in subscription mode
Create a Checkout Session from your backend. This example uses the public Checkout Session create shape.
curl https://api.paypercut.io/v1/checkouts \
-X POST \
-H "Authorization: Bearer $PAYPERCUT_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: checkout-subscription-01" \
-d '{
"mode": "subscription",
"ui_mode": "hosted",
"currency": "EUR",
"customer": "01HD7M6DRKZ4Q4QEVWJB0RC1S6",
"line_items": [
{
"price": "01HFRECURRINGPRICE000000000",
"quantity": 1
}
],
"success_url": "https://example.com/billing/success",
"cancel_url": "https://example.com/billing/cancel",
"client_reference_id": "user_123"
}'
Use client_reference_id or your own database row to connect the Checkout Session to your internal user or account.
Step 3: Send the customer to Checkout
Use the Checkout Session url returned by the API to redirect the customer, or render the session with the Paypercut checkout SDK if you are using embedded Checkout.
The success URL should show a confirmation or pending state. Do not grant production access only because the customer reached this URL.
Step 4: Handle server-side confirmation
Configure webhooks before going live.
At minimum, handle:
| Event | What to do |
|---|---|
checkout_session.completed |
Retrieve or store the Checkout Session and linked subscription. |
invoice.paid |
Grant or extend access for the paid billing period. |
invoice.payment_failed |
Start recovery and fetch the latest subscription and invoice state. |
Step 5: Store IDs and grant access
Store:
- your internal user, account, workspace, or tenant ID;
customer_id;price_id;checkout_session_id;subscription_id;- relevant
invoice_idvalues; - webhook event or delivery IDs for idempotency.
Grant or extend paid access after your backend processes a paid-period signal, such as invoice.paid, and maps the invoice back to the subscription and internal account.
Step 6: Test the flow
Before going live, test:
- Checkout Session creation.
- Hosted or embedded Checkout completion.
checkout_session.completeddelivery.invoice.paidhandling.invoice.payment_failedhandling.- Duplicate webhook delivery idempotency.
- The success URL when the webhook has not been processed yet.
Do not do this
- Do not grant access only from the success URL.
- Do not skip webhook handling.
- Do not use a one-time Price for subscription Checkout.
- Do not lose the mapping between your internal user or account and the Paypercut Customer or Subscription.
- Do not use PaymentIntent events as the primary subscription lifecycle source.
- Do not assume public
subscription.*webhooks exist. - Do not assume
send_invoiceis supported for this beginner path.

