Invoices API Updates

    Stripe has recently improved the clarity and expressiveness of the statuses that an invoice can have.

    Overview

    In previous versions of the Stripe API, Invoices did not have statuses. Instead, there was a series of booleans, like closed, paid, and forgiven.

    We’ve introduced statuses on invoices to better correlate Stripe invoices with finance workflows. Now, all Invoice objects have a status property. The status field can have the values draft, open, paid, void, and uncollectible.

    • The draft status indicates that an invoice is mutable.
    • The open status indicates that the invoice has been finalized, is no longer mutable, and is ready for payment.
    • The paid status indicates that the invoice has been paid in full.
    • The void status indicates that the invoice is no longer valid.
    • The uncollectible status indicates that the invoice is very unlikely to be paid, and could be considered a bad debt.

    For more details on these statuses, and the transitions between them, please see the invoicing workflow guide.

    Sample invoice timelines

    This section presents sample timelines for both one-off and subscription invoices, showing the statuses that both types of invoices can proceed through.

    One-off invoice example

    Here is an example timeline that a one-off invoice could go through. This sequence of events presents no changes from the pre-existing invoicing timeline, except that Stripe now exposes a status field to more clearly represent an invoice’s status.

    • Nov 24: Through the API, you might create an invoice that represents shipping 12 widgets to a customer. Stripe sends an invoice.created webhook, notifying you of the recently-created invoice. Looking at the API, you see that the invoice has status='draft'.
    • Dec 04: After reviewing the invoice, an accountant finalizes the invoice via the Stripe Dashboard. While the invoice is being finalized, its status is updated to status='open' and the finalized_at field is set. Stripe sends an invoice.finalized webhook, notifying you that the invoice was finalized.
    • Dec 04: Seconds later, Stripe sends the invoice via email, and begins retries. To help your CRM system keep track of when invoices are sent, Stripe sends an invoice.sent webhook each time it’s sent.
    • Dec 09: Your customer clicks the link in the email and pays the invoice using a Hosted Invoice Payment page. Unfortunately, they pay with an expired credit card. Their payment fails, and Stripe sends the invoice.payment_failed webhook notifying you of this failure.
    • Dec 11 (Today): With an updated credit card, the customer tries again. This time, the payment succeeds! Stripe sends the invoice.payment_succeeded webhook notifying you of this success, saves the card, and sets the invoice to status='paid'. If configured, Stripe also immediately emails your customer a receipt showing that the invoice was paid.

    Subscription invoice example

    Here is an example timeline for an invoice generated by a subscription.

    • Nov 21: Through the dashboard, you create a recurring subscription for a customer, configured for charging automatically. The subscription has a 20 day trial, so the first invoice will be in 20 days (Dec 11). Stripe sends a customer.subscription.created webhook.
    • Dec 08: Three days before the trial ends, Stripe sends a customer.subscription.trial_will_end webhook. Three days before charging the credit card would be a good time to send a trial reminder email.
    • Dec 11 (Today): At the end of the trial, a status='draft' invoice is created. Stripe sends an invoice.created webhook, notifying you of the recently-created invoice. After approximately one hour, the invoice is automatically finalized. This entails updating the status as 'open', setting finalized_at, and sending an invoice.finalized webhook.
    • Dec 11 (Today): Approximately one hour later, the invoice is automatically finalized. This entails updating the status as 'open', setting finalized_at, and sending an invoice.finalized webhook.
    • Dec 11 (Today): Soon after, Stripe attempts to charge the customer’s card on file. The customer’s payment succeeds. Stripe sends the invoice.payment_succeeded webhook to notify you of this success, and sets the invoice to status='paid'.

    New API methods

    Stripe has released a suite of new APIs for managing the status of an invoice. The new options, detailed in the upgrade checklist below, are:

    • Send an invoice: Stripe automatically sends and re-sends invoices via email. This endpoint, available via the Stripe API, allows you to send the invoice to your customer whenever you want.
    • Finalize an invoice: In the example above, the accountant finalized the invoice using the Stripe Dashboard. This functionality is also available via the Stripe API.
    • Void an invoice: Once an invoice has been finalized, it can’t be deleted. Voiding is used to indicate that the invoice was issued in error. You could consider voiding an invoice with an error in your company’s name, and then creating an entirely new invoice to replace it.
    • Delete a draft invoice: This action is applicable only to draft invoices. Deleted invoices aren’t visible through your Dashboard or the API. They cannot be un-deleted.
    • Mark an invoice uncollectible: Your accounting department might want to maintain a register of “doubtful debts” - that is, a list of invoices that are deemed to be uncollectible. You can use this API to tag applicable invoices.

    Upgrade checklist

    The following sections list functional changes in the Invoice object, and in invoice-related webhooks.

    Invoice object

    Stripe has added several fields to the Invoice object to help users better understand its status and behavior.

    finalized_at

    The new finalized_at field indicates the time at which the invoice was finalized. This is available for requests made on all API versions.

    status

    The new status field is available for requests made on all API versions. This replaces many booleans on the invoice, such as:

    • For requests made with the 2018-11-08 version and later, the paid=true boolean is removed. Check for the equivalent status='paid' instead.
    • For requests made with the 2018-11-08 version and later, the forgiven=true boolean is removed. Check for the equivalent status='uncollectible' instead.

    auto_advance

    The new auto_advance field indicates whether automatic collection is active. For the 'draft' and 'open' statuses, the auto_advance field can be updated. Otherwise, auto_advance will always be false.

    When auto_advance=false, Stripe will not:

    • Automatically issue draft invoices
    • Automatically send the first (or reminder) emails for billing='send_invoice' invoices
    • Automatically attempt the first (or retry) payments for billing='charge_automatically'invoices
    • Automatically reconcile inbound credit transfers with the invoice

    For invoices with the statuses 'uncollectible', 'void', and 'paid', the auto_advance field is always false.

    On versions prior to 2018-11-08, the closed field is still present, and equal to the inverse of auto_advance. For example, auto_advance=true is equivalent to closed=false (and vice versa). Invoices created using prior API versions will continue to default to closed=false.

    Webhooks

    With this update, we’ve introduced three new webhooks:

    • invoice.finalized: Sent when an invoice is finalized.
    • invoice.voided: Sent when an invoice is voided.
    • invoice.marked_uncollectible: Sent when an invoice is marked uncollectible.

    The existing invoice.created webhook is sent upon creating an invoice. If your webhook handler needs to differentiate between one-off invoices and invoices generated by a subscription, check for the existence of the invoice.subscription property in the webhook body.

    These pre-existing webhooks are unchanged:

    • invoice.sent: Sent when an invoice is emailed to a user, either automatically, through the API, or in the Dashboard.
    • invoice.deleted: Sent when a draft invoice is deleted, either through the API or in the Dashboard.
    • invoice.payment_succeded or invoice.payment_failed: Sent when an attempt to pay an invoice succeeds or fails.

    Questions?

    We're always happy to help with code or other questions you might have! Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.