#lexumi_best-practices
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/1348749163357274183
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
๐
Hello :)
On this update are there different billing periods?
Do you have an example I could look at?
The addons can only be booked per month
ive tried to set the quantity to 0 for the last item here but it just send the customer.subscription.updated right away
if (body.length > 0) {
for (const addon of body) {
const subscriptionItemId = addon.subscriptionItemId;
const subscriptionId = addon.subscriptionId;
if (!subscriptionId || !subscriptionItemId) continue;
try {
// Fetch current subscription to get all items
const subscription = await stripe.subscriptions.retrieve(subscriptionId);
// Ensure we have valid items
if (!subscription.items || !subscription.items.data) continue;
// Modify only the target item (set quantity to 0)
const updatedItems = subscription.items.data.map((item) => ({
id: item.id,
quantity: item.id === subscriptionItemId ? 0 : item.quantity,
}));
// Update the subscription with modified items
await stripe.subscriptions.update(subscriptionId, {
proration_behavior: "none",
items: updatedItems,
});
} catch (error) {
console.error("Error updating subscription:", error);
}
}
}
}
This was my remove addons test function
Can you share a Subscription ID that you tested with?
The update will always occur immediately, but the customer won't be charged again until the next billing cycle if you aren't changing the billing period here.
If you don't want the actual update to occur immediately then you would need to use a Subscription Schedule: https://docs.stripe.com/billing/subscriptions/subscription-schedules
sub_1R0lCXG63VjhDQbDm1wsJt7j
that would be the sub id of my test account
the update would be fin,e but as we are retrieving the addons from the subscription object that is set from customer.subscription.create/update an immdeiate update would result in the user loosing the addon even though he paid at that month for it
So something like this?
if (body.length > 0) {
for (const addon of body) {
const subscriptionItemId = addon.subscriptionItemId;
const subscriptionId = addon.subscriptionId; // Ensure this is available
if (!subscriptionId || !subscriptionItemId) continue;
try {
// Fetch the current subscription
const subscription = await stripe.subscriptions.retrieve(subscriptionId);
if (!subscription.items || !subscription.items.data) continue;
// Check if a Subscription Schedule already exists
let schedule = await stripe.subscriptionSchedules.list({
customer: typeof subscription.customer == "string" ? subscription.customer : subscription.customer.id,
limit: 1,
});
let scheduleId = schedule.data.length > 0 ? schedule.data[0].id : null;
if (!scheduleId) {
// Create a Subscription Schedule if none exists
console.log("Creating new Subscription Schedule...");
const newSchedule = await stripe.subscriptionSchedules.create({
from_subscription: subscriptionId,
end_behavior: "release", // Keeps the subscription running after the schedule ends
});
scheduleId = newSchedule.id;
}
// Modify the schedule to remove the item in the next phase
console.log("Updating Subscription Schedule...");
const updatedPhases = [
{
items: subscription.items.data.map((item) => ({
price: item.price.id,
quantity: item.id === subscriptionItemId ? 0 : item.quantity,
})),
start_date: subscription.current_period_end,
},
];
await stripe.subscriptionSchedules.update(scheduleId, {
phases: updatedPhases,
});
console.log("Subscription Schedule updated successfully.");
} catch (error) {
console.error("Error updating subscription schedule:", error);
}
}
}
}
Best thing to do is test it out in test mode with a test clock: https://docs.stripe.com/billing/testing/test-clocks !
You'll need to pass the current phase as phase 0 and the new phase as phase 1
shouldn i see the schedules on my subscription in the dashboard?
There should be an indication, yes.
Don't recall exactly what it looks like off the top of my head (we focus on the API and don't use the Dashboard much)
cause it seems like the subscription has one, but non is shown
Can you share the Subscription ID?
sub_1R0lCXG63VjhDQbDm1wsJt7j still the same
Yeah the schedule doesn't have any future phases on it.
So that's why it doesn't indicate anything in the Dashboard
Your update request likely didn't do what you intended: https://dashboard.stripe.com/test/logs/req_3JuGOyOb70j6Ea
{
"phases":{
"0":{
"items":{
"0":{
"price":"price_1QpVljG63VjhDQbDmIGj7qob",
"quantity":"3"
},
"1":{
"price":"price_1QmYMgG63VjhDQbD6s07laiK",
"quantity":"3"
},
"2":{
"price":"price_1QpVu2G63VjhDQbDQxlb6d4o",
"quantity":"1"
}
},
"start_date":"1741531897"
}
}
should i have set
"2":{
"price":"price_1QpVu2G63VjhDQbDQxlb6d4o",
"quantity":"0" <- quantity 0
}
?
Phase 0 should be the current items on the Subscription and Phase 1 should be what you want to update to
Okay i think ill need some time to correctly implement this ๐
Sounds good! As my teammate mentioned, the best thing to do is to use test clocks in test mode to play with this
yeah im still trying to get the creaton working..
const subscriptionSchedule = await stripe.subscriptionSchedules.create({
customer: customerId,
start_date: subscription.created,
end_behavior: 'release',
phases: [
{
items: [
{
price: '',
quantity: ,
},
],
},
],
});
When creating the subscription schedule, how do i set the subscription its for? and also do i provide all items of the subscription or just the item that should be updated?
You'll need to do this in two requests:
- Create the Schedule and pass an existing Subscription ID as the value for
from_subscription: https://docs.stripe.com/api/subscription_schedules/create#create_subscription_schedule-from_subscription - update the newly-created Schedule. When you update the Schedule, you'll need to include the current Phase and all future Phases: https://docs.stripe.com/api/subscription_schedules/update#update_subscription_schedule-phases
does the current phase already exist or do i have to create that somehow?
Current phase should already exist. You should see it in the response to your create request
so something like this?:
try {
// Fetch the current subscription
const subscription = await stripe.subscriptions.retrieve(subscriptionId);
let customerId: string | null = null;
if (typeof subscription.customer === "string") {
customerId = subscription.customer;
} else if (subscription.customer && "id" in subscription.customer) {
customerId = subscription.customer.id;
}
if (!customerId) {
console.error("No valid customer found for subscription:", subscriptionId);
continue;
}
const subscriptionSchedule = await stripe.subscriptionSchedules.create({
from_subscription: subscriptionId,
});
console.log(subscriptionSchedule);
const currentItems = subscription.items.data;
const updatedItems = currentItems.map((item) => ({
id: item.id,
plan: item.plan.id,
price: item.price.id,
quantity: item.id === subscriptionItemId ? 0 : item.quantity, // Set to 0 if it matches
}));
await stripe.subscriptionSchedules.update(subscriptionSchedule.id, {
phases: [
{ ...(subscriptionSchedule.phases[0] as Stripe.SubscriptionScheduleUpdateParams.Phase) }, // include phase 0?
{ start_date: subscriptionSchedule.phases[0].end_date, items: updatedItems },
],
});
} catch (err) {
console.log(err);
}
what do i set the end_date of phase 1 to?