Invoices

Invoices record what Paypercut attempted to collect for a billing period. Use them to reconcile subscription charges, provision access after a successful payment, and recover when a recurring payment fails.

Invoices are created by billing flows such as subscription creation, subscription renewal, and automatic retry attempts. The invoice object returned by the API is the same object sent in invoice webhook events.

How invoices fit into subscriptions

A subscription controls the recurring agreement with the customer: items, prices, billing interval, trial state, and cancellation rules. An invoice records a specific billing period and the payment attempts made to collect it.

For a subscription renewal, the flow is:

  1. Paypercut reaches the next billing date for the subscription.
  2. Paypercut creates an invoice for the billing period and subscription items.
  3. Paypercut attempts to collect the invoice using the subscription payment method.
  4. Paypercut sends an invoice event with the invoice in data.object.
  5. Your integration updates access, fulfillment, notifications, or recovery state based on the event type.

Invoice events

Subscribe to invoice events when your system needs to react to recurring billing outcomes.

Event When it is sent Typical action
invoice.paid The invoice was successfully paid. Grant or continue access, mark the billing period as paid, and fulfill any subscription delivery tied to the period.
invoice.payment_failed Paypercut attempted to collect payment for the invoice and the attempt failed. Notify the customer, prompt for a new payment method, and keep access behavior aligned with the subscription status.

The event data.object is the invoice resource. Use data.object.id as the invoice identifier and data.object.parent.subscription_details.subscription to connect the invoice back to the subscription when the invoice was generated from subscription billing.

{
  "id": "01KA9TBINVOICEPAID123456",
  "type": "invoice.paid",
  "created": "2026-03-01T00:00:12Z",
  "livemode": true,
  "data": {
    "object": {
      "id": "01KA9TBINVOICE123456789",
      "object": "invoice",
      "customer": "01KA9SXYZ123456789ABCDEFGH",
      "status": "paid",
      "billing_reason": "subscription_cycle",
      "collection_method": "charge_automatically",
      "currency": "USD",
      "amount_due": 2000,
      "amount_paid": 2000,
      "amount_remaining": 0,
      "parent": {
        "type": "subscription_details",
        "subscription_details": {
          "subscription": "01KA9TSUBSCRIPTION123"
        }
      }
    }
  }
}

Handle paid invoices

Treat invoice.paid as the billing signal that the invoice amount has been collected.

Common actions:

  • Mark the billing period as paid in your system.
  • Grant or continue access for the subscription period in period.start and period.end.
  • Fulfill the product, media, or delivered resource associated with the invoice line.
  • Store the invoice ID so repeated webhook deliveries do not trigger duplicate fulfillment.

If your integration receives a separate event when delivered media or a delivered resource expires, process it as a resource lifecycle event. Use the event type as the action and the data.object payload as the resource that changed. Do not infer expiry from invoice.paid; invoices describe billing state, while delivered resources describe access or fulfillment state.

Handle failed invoice payments

Treat invoice.payment_failed as the signal that Paypercut could not collect the invoice on that attempt.

Common actions:

  • Notify the customer that payment failed.
  • Ask the customer to update their payment method.
  • Keep access behavior aligned with your subscription rules and the subscription status.
  • Inspect payments.data to see the failed invoice payment attempt.
  • Use amount_remaining to show the outstanding amount.

Payment failures can happen on the first invoice or on a renewal invoice. Use the invoice parent and billing_reason fields to decide which recovery flow to show in your product.

An invoice.payment_failed event does not mean the invoice status is payment_failed. The invoice usually remains open while payment is still due, and the failed attempt appears in payments.data.

Invoice object

Important fields for integrations:

Field Description
id Unique invoice identifier.
status Current invoice lifecycle status, such as open, paid, void, or uncollectible.
customer Customer associated with the invoice. In the API reference, pass expand[]=customer to return the full Customer object.
amount_due, amount_paid, amount_remaining Monetary totals in the smallest currency unit.
period Billing period covered by the invoice.
parent Resource that caused the invoice to be created. Subscription invoices include subscription_details.subscription.
lines Invoice line items. Each line can include pricing and subscription item details.
payments Payment attempts made to collect the invoice.
status_transitions Timestamps for lifecycle transitions such as finalization and payment.
metadata Merchant-defined key-value data copied onto the invoice.

Implementation checklist

  1. Configure a webhook endpoint and subscribe to invoice.paid and invoice.payment_failed.
  2. Verify webhook signatures before parsing the event.
  3. Process webhook events idempotently by storing the event ID or invoice ID and event type.
  4. Retrieve the invoice from the API when your handler needs the latest state before making a customer-visible decision.
  5. Keep billing state separate from fulfillment state when you also consume delivered or expired resource events.