Invoices and payment collection

Invoices are the billing-period record for subscription integrations. Use invoice events to decide when a paid period exists, when access should be extended, and when payment recovery should begin.

What this page covers

  • Why subscriptions create invoices
  • What invoice.paid means
  • What invoice.payment_failed means
  • How invoice and payment state should affect access decisions
  • How Payment and PaymentIntent events fit into reconciliation

Before you use this page

Read How subscriptions work and choose a creation flow. For the beginner path, start with Create subscriptions with Checkout.

Why invoices matter

A subscription describes the recurring agreement. An invoice describes a specific billing period and the payment attempts made to collect it.

For a subscription integration, your backend should treat invoices as the billing-period source of truth:

  1. A subscription reaches a billing moment.
  2. Paypercut creates or updates an invoice for that billing period.
  3. Paypercut attempts to collect payment.
  4. Paypercut sends an invoice event.
  5. Your backend grants, extends, or recovers access based on the event and latest state.

Initial and renewal invoices

Subscription-related invoices can represent different billing moments:

Billing moment Typical meaning
Initial subscription billing First paid period for a new subscription.
Renewal billing A later billing period for an existing subscription.
Retry or recovery attempt Another attempt to collect an invoice that was not paid.

Use the invoice parent and billing_reason fields when you need to understand why the invoice exists. Subscription invoices include parent subscription details that let you connect the invoice back to the subscription.

invoice.paid

Use invoice.paid as the main paid-period signal.

When your backend receives invoice.paid:

  1. Verify the webhook signature.
  2. Process the event idempotently.
  3. Read the invoice ID from data.object.id.
  4. Read the linked subscription from data.object.parent.subscription_details.subscription when present.
  5. Map the subscription to your internal user or account.
  6. Grant or extend access for the paid billing period.
  7. Store the invoice ID and processing result.

Do not process a paid invoice twice if the webhook is delivered more than once.

invoice.payment_failed

Use invoice.payment_failed as the payment recovery signal.

When your backend receives invoice.payment_failed:

  1. Verify the webhook signature.
  2. Process the event idempotently.
  3. Identify the invoice and linked subscription.
  4. Fetch the latest invoice or subscription state if your access decision depends on current status.
  5. Notify the customer or show recovery UI.
  6. Keep access behavior aligned with your product policy and subscription state.

An invoice payment failure means collection failed for that attempt. It does not mean every subscription should immediately lose access. Define your access policy and reconcile against latest state before taking customer-visible action.

Payment and PaymentIntent events

Payment and PaymentIntent events can help support teams debug payment attempts, provider responses, and reconciliation. They are not the main subscription access contract for the beginner path.

Use invoice events for subscription billing-period decisions because invoices connect the billing period, customer, subscription, amount, status, and payment attempts.

Access decisions

Situation Recommended backend action
invoice.paid for a subscription invoice Grant or extend access idempotently.
invoice.payment_failed Start recovery and fetch latest state before changing access.
Payment event without invoice context Use for support or reconciliation; do not grant subscription access from this alone.
Browser success redirect Show pending or confirmation UI; do not grant production access from this alone.

Troubleshooting

Symptom Check
Paid customers do not receive access Confirm invoice.paid is subscribed, delivered, signature-verified, and mapped to the internal account.
Access is granted twice Store processed event IDs or invoice IDs with the action taken.
Failed renewals are missed Confirm invoice.payment_failed is enabled for the webhook endpoint.
Support cannot match a payment to a subscription Use invoice parent subscription details and invoice payment data before falling back to payment-level events.

Unsupported in this beginner path

Do not document or build this path around send_invoice. The current beginner subscription flow uses automatic collection with Checkout and invoice events.

Next