#tea-hanks_api
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1476892548340514817
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
And this is an example of another request where the user does not have a schedule hence we use subscription details in the preview invoice args. This works fine even if subscription has a coupon that is deleted
req_hzQAlRKZZJmyS8
hi there!
However if the subscription had a schedule and the next phase of schedule is using the coupon that has now been deleted causes the preview invoice API to fail.
that seems expected, no? what would you want to happen instead?
So there are two cases. We had one subscription with no schedule using a coupon which is valid for 12 months. When we preview invoices for it, it works even if the coupon is deleted
And then we have another subscription which had a schedule even before the deletion of coupon. The subscription had a schedule to change prices at the end of the billing period and continue using the same coupon.
I would expect it would work similar to the above case. That is for existing subscription the preview invoice should show the discount for the next phase too. However, it doesn't. In case of schedule phases it tries to validate the coupon
Now I tried to simulate the subscription with schedule to advance in time. Turns out it does transition to next phase and it works. Just the preview invoice doesn't work
๐ taking over as my colleague needs to step away
could you share the request ID for your preview invoice call? (req_123)
This is the one req_TQP96xIznVCDid
thanks, taking a look into the error
could you also share the request that succeeded with a deleted coupon (i.e. the one for the subscription with no schedule)
Yes. There you go req_hzQAlRKZZJmyS8
thanks
looks like the reason that request didn't get the same error is because the deleted coupon wasn't passed in the request parameters
the idea with schedule_details in the preview invoice API is that it allows you to preview a change to the schedule (i.e. creating a new discount by applying the coupon)
since it wouldn't be possible to apply a deleted coupon to the subscription, that's why the request errors out
this is a little different with your second example
the deleted coupon was used to create a discount on the subscription, and that discount persists even after the coupon is deleted
but if you tried to create (or preview) a new discount on the subscription using the deleted coupon (i.e. by passing the coupon in subscription_details), you'd get the same resource_missing error
So I created a subscription with a monthly sub. Then I scheduled an update to switch it to another tier of monthly sub at the end of current billing period. The inital sub had a discount attached to it for 12 months. And when I was scheduling an update it had the same discount
This is the request id for the schedule req_FaL4WeWIdeQwvv
Now I deleted the coupon and sent a preview invoice request. This is the ID req_Mvhh0mpcJTwuGW. You can see in the request body it has schedule details because as I mentioned above the subscription has a schedule. Given by your previous response I did not include the discount coupon in the request. If I do include it then it fails req_aMCupGhz3nQ2PY. This is consistent with your explanation
Now to test it further I advanced the subscription by one month so that the subscription comes in the next phase. Given by your explanation the new phase should not be able to apply the deleted coupon to the subscription. However, when I advance the subscription I get an invoice that in fact does include the discount and the subscription advances to the next phase with discount. This is the event id where the invoice was created evt_1T5Pc3Fd6EDIZfQWr3vTjoZo
This brings us to my confusion. Preview invoice API fails but the subscription transitions successfully. I can try to preview without providing discount args as done in this request req_Mvhh0mpcJTwuGW but it shows incorrect about that will be charged. It shows an amount without discount. Btw not sure if you can access it but this is the new invoice ID in_1T5Pc1Fd6EDIZfQWUIa2skYA
What I would expect is that if subscription can transition into a new phase where there is a deleted discount I should be able to preview invoice for it too. However, that is not the case
Going forward I will avoid deleting coupons and resort to other solutions but I am stuck what to do about the current ones
๐ taking over for my colleague. Let me catch up.
When a subscription schedule actually transitions to a new phase that references a deleted coupon, our system silently drops the deleted coupon and the transition succeeds (which is why your subscription advanced just fine and the invoice included the discount from the existing subscription-level discount object).
However, the preview invoice API treats coupons passed in schedule_details.phases[].discounts as if they're being newly applied, so it validates them and returns a resource_missing error for deleted coupons. This is the inconsistency you identified โ the preview doesn't simulate what would actually happen during the transition. This is the expected/designed behavior on our side.
Workarounds for now:
- If you have the discount ID (e.g. di_xxx) from the existing subscription/phase, you can pass that in the discount field of the discounts array instead of the coupon field. Existing discounts persist even after the underlying coupon is deleted.
- Going forward, rather than deleting coupons, consider setting max_redemptions to the current redemption count to prevent new uses while keeping existing references intact.
Ahh okay interesting. So at the time of transition the coupon specified in the phase is dropped and instead the existing discount on the subscription is taken
And I have another question and this might be a tangent. The only reason we included the coupon in the next phase was to make sure the user continues to get that discount. Assuming a user subscribes with a 10% off for 3 months and we schedule an update for the second month. We wanted the user to get that discount with the updated sub for the remaining two months
Given your explanation of discount being taken from existing sub I guess we could have just removed the coupon from the next phase and schedule an update and the updated subscription would still have that discount right?
Great question, but unfortunately no โ you can't just remove the coupon from the next phase and expect the discount to carry over automatically.
Each schedule phase explicitly defines what the subscription should look like. When the subscription transitions to a new phase, the system compares the phase's specified discounts against the subscription's existing discounts:
If the new phase includes the same coupon, the system tries to reuse the existing discount (no re-redemption needed) โ and this is actually what makes the phase transition succeed even with a deleted coupon. The system sees "oh, there's already a matching discount on the subscription for this coupon" and just keeps it.
If the new phase doesn't include any coupon/discount, the system interprets that as "this phase should have no discounts" and removes the existing discount from the subscription.
So the reason the coupon needs to be in the next phase is precisely to signal "keep using this discount." The irony is that the actual transition handles this gracefully (reuses the existing discount, silently drops it if validation fails), but the preview invoice API fails because it validates the coupon before ever getting to that reuse logic.
For your current situation (coupons already deleted), the best workaround is to pass the discount ID (di_xxx) instead of the coupon ID in schedule_details.phases[].discounts. You can get the discount ID from the subscription object. Existing discount objects persist even after the underlying coupon is deleted, and the API should accept them without the resource_missing error.
Hmm passing the discount id instead of coupon id shouldn't be as straight forward I guess
To make it clear what I mean here. Assume my subscription has a discount. Then I schedule a phase where a different coupon is used
Now if I pass existing discount Id instead of coupon for all phases i.e. current one and the next one then the preview might be incorrect
What I am assuming here is that you mean if there is a coupon in the phase I first check if there is already a discount in the subscription for that coupon. If yes then use the discount id. If not then use the coupon id
Given by that logic in my preview invoice params for the current phase I will have a discount id. And for that next phase where a different coupon is used I will not find any existing discount on the subscription so I will use the coupon id
And now to be very pedantic and complete the full cycle. It is not guaranteed that the coupon id passed for new phase might correspond to an existing coupon
Hence in the end what I need to do
- For a coupon id check if discount exists in sub. If yes then use that discount id. Because if coupon is deleted then the API doesnt fail. If coupon exist then well the discount is carried over (here I am assuming the discount duration doesn't restart)
- If no discount is found against a coupon id then make sure if coupon exists. If yes then pass it as args otherwise drop it from args
I hope I was clear
You were very clear, and your logic is exactly right! Let me confirm the key assumptions:
The discount duration does NOT restart โ When the system reuses an existing discount across a phase transition, it keeps the original discount object with all its original properties (start date, duration, etc.). So passing the discount ID is safe; it will continue counting down from when it was originally created.
Your algorithm is correct. To summarize what you laid out:
For each phase in schedule_details, for each coupon referenced in that phase's discounts:
- Check if the subscription already has an active discount (
di_xxx) for that coupon โ if yes, use the discount ID - If no existing discount is found, check if the coupon still exists โ if yes, use the coupon ID
- If the coupon is deleted and there's no existing discount โ drop it from the args
This correctly mirrors what the actual phase transition would do.
One caveat: When you pass a discount ID for a future phase (not the current one), the API may reject it if it doesn't recognize the discount as already belonging to the subscription. I'd recommend testing this with a future phase to make sure the discount ID is accepted there too. If it isn't, the fallback would be to drop the deleted coupon from future phase args and accept that the preview amount won't be 100% accurate for those phases.
I think that sums up our discussion. This was greatly helpful. Thank you for the very detailed and insightful discussion
Have a nice weekend ahead ๐
thanks! same to you
These threads dont get deleted right? I will reference it in our docs or somewhere to get working on it on Monday