Subscription canceled_at

98 views
Skip to first unread message

Michael Frederick

unread,
Mar 20, 2015, 2:14:33 PM3/20/15
to api-d...@lists.stripe.com

tldr;

For the Subscription object:

Why is there a timestamp field for the status of canceled but not other Subscription statuses ('unpaid', 'past_due')?

Why is it canceled_at and not status_assigned (or status_changed_at)?


I'd love it I'm missing something, thanks in advance for reading.


Subscription Payment Failure workflow

When a Subscription arrives at the final stage of the Payment Failure workflow, you can set the status of a Subscription to 1 of 3 statuses:


  • past_due

  • canceled

  • unpaid


We tried each of them, we weren’t certain what fit our needs the most. Finally settling on ‘unpaid’. We primarily chose ‘unpaid’ so that a Customer could easily continue the same Subscription they signed up with, without having to store that Subscription anywhere (except in Stripe), as well as give us the option to reopen Invoices that were missed.


We feel pretty confident ‘unpaid’ is exactly what we want, but there is a ‘gap’ in what the API provides for ‘past_due’ and ‘unpaid’ versus the ‘canceled’ status.


Reporting 'requirements' we have:

1) Give me a list of Customer’s with ‘unpaid’ Subscriptions.


That’s easy, we’re storing the Subscription data on our side and we have easy access to it.


2) Give me a list of Customer’s who have Subscriptions that entered into the status of ‘canceled’ in the last 3 months.


That’s also easy, grab everyone who has a status of ‘canceled’ where the ‘canceled at’ timestamp is in the last 3 months.


3) Give me a list of Customer’s who have Subscriptions that entered into the status of ‘unpaid’ in the last 3 months.


The only solution I see is storing all of the invoice data on our side, and querying to find out at what Date a Subscription became 'unpaid'.


‘canceled_at’ seems really specific to the status of ‘canceled’, what if that was more generically ‘status_changed’ (timestamp) or ‘status_assigned_at’ (timestamp)?


Cheers,

Freddy


Michael Frederick

unread,
Apr 10, 2015, 9:25:37 AM4/10/15
to api-d...@lists.stripe.com
Anyone have thoughts on this? Aside from looking at Invoices, is there any other way to find out when a Customer's Subscription moved into the status of 'unpaid'?

Peter

unread,
Apr 10, 2015, 10:15:43 AM4/10/15
to api-d...@lists.stripe.com
Hi Freddy,

There currently isn't any way to find what time a subscription transitioned into the unpaid state just by looking at the subscription itself.

This sounds like a reporting concern, though, so would it be acceptable to list out all invoices from the last 3 months via the API, and then find out from those which invoices are unpaid, and which subscriptions they link to? Generally, the less state you have to sync up with an external service, the better, so it may be a good idea not to try to keep invoices synched in your database, and just download them via the API when you need to run the report.

The upshot of all of this, though, is that there currently is no way of doing this other than with the invoice.

- Peter

Michael Frederick

unread,
Apr 10, 2015, 11:05:28 AM4/10/15
to api-d...@lists.stripe.com
Peter,

Thank you for the response, really appreciate it.

Likely the best solution for us going forward will be a combination of back-filling data by looking at the Invoices, as well as, updating data locally in real-time when a webhook comes through for a Subscription changing to an unpaid status. A lot more work, but it sounds do-able.

Locally (in our database table of Subscriptions), I am going to make the proposed change away from canceled_at to status_assigned_at.

I would love to hear the rationale behind why the Stripe API specifically calls out canceled_at but not past_due_at or unpaid_at.

I'm not sure I'm following why Invoices being the only way is an 'upshot'?

Again, thank you for the response.

Freddy

Peter

unread,
Apr 10, 2015, 11:38:27 AM4/10/15
to api-d...@lists.stripe.com
Hi Freddy,

Ah, you're right actually. The above email response is good evidence that I shouldn't answer any emails before the morning caffeination. If you already have the event data from the webhooks, that's probably the best way to determine when a subscription became unpaid. You can also retrieve 'customer.subscription.updated' events to backfill this data if you don't store it locally.

The reason that cancelled_at is special is mostly a historical artifact. It's essentially a known deficiency of the subscriptions API that there currently isn't a good way to see how a subscription was changed over the course of its lifetime. You can imagine that tacking on many `<some_action>_at` timestamp fields onto a subscription isn't the best solution for this problem, and we're hoping to do better than that. This will probably end up being some kind of augmentation of the current events API.

- Peter

Michael Frederick

unread,
Apr 10, 2015, 12:20:16 PM4/10/15
to api-d...@lists.stripe.com
Certainly not holding the caffeine deprived response against you, I'm more than groggy without that first cup or two.

Excellent point about Event data, we don't store the Event data, and I had excluded that approach because of the '30 day guarantee', but it appears to be available much further back. Thank you!

I think the historical piece is fine (says the guy who hasn't had to answer that question yet). It makes sense to me that you'd need to look at Invoices and Charges to get the full story of what happened to a Subscription. 

The problem I'm solving is summarizing the current state of all our Subscriptions. Generalizing to a 'status_assigned_at' instead of 'canceled_at' let's you have as many Subscription states/actions as you want, and an easy way to report on those states just by looking at the Subscription object.

Love the Stripe API by the way, really appreciate how well done it is, and the continuous improvements to it.

Thanks,
Freddy

Will Lord

unread,
Apr 16, 2015, 9:21:10 AM4/16/15
to api-d...@lists.stripe.com
Hi Freddy,

We were having a very similar problem with our reporting and eventually went for the event approach.

We retry payments so our unpaid subscribers follow this flow: Active -> Past_Due -> Unpaid

We're now pulling every customer.subscription.updated event that signals a customer moving into the unpaid state by comparing the current and previous attributes of the customer. If they were previously past_due and are now unpaid I know (or at least I think I know!) that that customer can be added to a report of unpaids.

That's by no means the most complicated bit of event wrangling we've had to pull off for reporting purposes. The API is really powerful but some more consistency in the data that's returned when customers move between states would be extremely useful I think.

Will

Michael Frederick

unread,
Apr 16, 2015, 9:54:29 AM4/16/15
to api-d...@lists.stripe.com
Will,

Thanks for responding. Glad to hear I'm not alone, and that the event approach is a viable solution. 

We're starting down the path of tracking these states, specifically with Subscriptions, in more detail, we've recognized the fact that it's much easier to re-engage someone you already have/had than to find someone new.

The API is definitely powerful but there are always room for improvements.

Are you then moving the Subscriptions into a 'canceled' state after a period of time? Or is 'unpaid' the last state they end up at?
Reply all
Reply to author
Forward
0 new messages