You can upgrade or downgrade an active subscription by changing the product associated with it. However, free trials associated with the new product are ignored. To apply a free trial period to an upgraded or downgraded subscription, apply the change from the Activity page.
Subscription Update Flags
The following flags modify behavior when used in conjunction with product paths as part of a subscription change request.
Prorate
Editing a subscription with prorate flag set to true will first calculate the remaining balance on the subscription before the changes are applied, then apply the changes and either deduct the balance from the applicable remainder charges (for upgrades) or refund/credit the buyer for the excess charges (for downgrades).
A proration order is created for the changes made accessible under the subscription detail page on the FastSpring app
Preview
The preview flag in combination with prorate flag returns a response of proratable charges and credits for a recent and eligible plan change.
Prorate | Preview | Behavior |
---|---|---|
true | false | The POST to subscriptions endpoint calculates the charges and credits resulting from the subscription changes, prorate the changes, and commits the changes accordingly. It returns a response based on the success/failure of the subscription change update. |
true | true | The POST to subscriptions endpoint should calculate the charges and credits resulting from the subscription changes, prorate the changes and return the estimates as a response. It will NOT commit the changes. |
false | true | Not Supported |
false | false | The POST to subscriptions endpoint modifies the subscription as requested. It does NOT prorate the proposed changes. It also does NOT return a response containing a preview of the changes. It will return a response based on the success/failure of the subscription change update. |
Modify the primary subscription product path, quantity, next charge date, or coupon
An upgrade is when your monthly recurring revenue increases after the change, otherwise the change is marked as a downgrade. The POST
method allows modification of not just the primary product, but also other details on the subscription like dates, coupons, or quantity.
{
"subscriptions": [
{
"subscription": "subscription-uuid-1", // Subscription ID to be updated (From Subscription detail page)
"product": "new-monthly-subscription", // Catalog product path of the new subscription primary product from the catalog
"quantity": 1, // quantity of the new product
"coupons": ["coupon_code"], // only supports one coupon to be applied, pass an empty array to remove coupon
"prorate" : true // If true the subscription is prorated upto the day of API call - any refunds are applied as credit to the remaining period
}
]
}
{
"subscriptions": [
{
"subscription": "subscription-uuid-2",
"next": 1712188800000, // or "yyyy-mm-dd", // Next charge date (UTC epoch time in millis) - Setting next date in past returns an error
"end": "2024-12-01", // or UTC Millis or 0, // Last charge date will be on or before this date. 0 as unlimited (indefinitely renews) subscription
"product": "subscription-product-1",
"quantity": 1,
"coupons": ["valid_coupon_code"], // Only supports one coupon to be applie. Pass an empty array to remove coupon.
"prorate": false // When implementing proration. Cannot prorate with updating next charge date.
}, ...
]
}
Error handling: setting next
date in the past
next
date in the pastWhen you modify the next charge date, it must be in the future. If you try to update the subscription immediately by setting a time in the past, FastSpring will return an error:
{
"subscriptions": [
{
"subscription": "subscription-uuid-2",
"next": 1448496000000, // This equals November 26, 2015 (UTC) and generates an error.
"end": "2024-12-01",
"product": "subscription-product-1",
"quantity": 1,
"coupons": ["valid_coupon_code"],
"prorate": false
}
]
}
{
"action": "subscription.update",
"subscription": "subscription-uuid-2",
"result": "error",
"error": {
"next": "Please choose a next period date after the current date."
}
}
// To avoid this error, verify that the next charge date is in the future.
Modify the price or discount for an active subscription without changing the product, programmatically apply a discount without changing the product
{
"subscriptions": [
{
"subscription":"subscription-id-1",
"pricing":{
"price": {"USD":10}
}
}
]
}
{
"subscriptions": [
{
"subscription":"subscription-uuid-4",
"pricing":{
"price":{"USD":10}, // see note below about currency
"discount":{
"type":"amount",
"amount":3.5, // (OR can be "amount" : {"USD":3.50}, ) see note below about currency
"duration":"all" // indefinitely apply discount
}
}
}
]
}
// Note: If the currency is not specified, the currency of the subscription instance will be used;
// if the currency is specified and differs from the subscription's currency, the amount will be converted to subscription's currency.
{
"subscriptions": [
{
"subscription":"subscription-uuid-3",
"pricing":{
"price": 9.95, // see note below about currency
"discount":{
"type":"percent",
"percentage":5, // (OR can be "amount" : {"USD":3.50}, ) see note below about currency
"duration":2 // (OR "all") - restrict discount to periods specified in duration (2 periods for monthly will give 5% discount for 2 monthly rebills)
}
}
}
]
}
// Note: If the currency is not specified, the currency of the subscription instance will be used; if the currency is specified and differs to the subscription's currency, the amount will be converted to subscription's currency.
Resume a canceled subscription
By default, FastSpring deactivates canceled subscriptions on the next rebill date. Until that date, you can resume a subscription. Customers will be rebilled as if you never canceled it.
To resume a canceled subscription, the body of your request must include the deactivation
parameter with a value of null
, like in the following example:
{
"subscriptions":[
{
"subscription":"OapmwBYlS8CE36nlo7Vm9w",
"deactivation":null
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "OapmwBYlS8CE36nlo7Vm9w"
}
]
}
Error handling
If validation fails, you could get one of these responses:
{
"action": "subscription.update",
"subscription": "OapmwBYlS8CE36nlo7Vm9w",
"result": "error",
"error": {
"uncancel": "Subscription is not active."
}
},
// You'll get this error if you try to uncancel a subscription that's already been deactivated.
{
"action": "subscription.update",
"result": "success",
"subscription": "OapmwBYlS8CE36nlo7Vm9w"
}
]
}
// You'll get this response if you try to uncancel a subscription that's not been canceled.
Omitting the deactivation
parameter
deactivation
parameterIf you omit "deactivation":null
from your request, FastSpring will return a success
response, even though the subscription is still canceled:
{
"subscriptions":[
{
"subscription": "OapmwBYlS8CE36nlo7Vm9w"
}
]
}
// This request omits "deactivation":null.
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "OapmwBYlS8CE36nlo7Vm9w"
}
]
}
// The response returns "result": "success", but the subscription is still canceled.
// Try again with "deactivation":null included in the request body.
Add or edit subscription addon to an active subscription
A Subscription Add-on product path is a standalone non-subscription product path from the catalog - which has been marked in the subscription product as an Add-on Related Offer. Addons renew along with the subscription so the price on the Addon is assumed periodic and not one-time charge.
{
"subscriptions": [
{
"subscription": "subscription-uuid-1",
"addons": [
{
"product": "add-on-seats-being-added-or-updated", // Catalog product path must be in catalog AND marked as relationship to base/parent subscription product
"quantity": 20, // update quantity of addon (this can be used for variable component price or usage based pricing like seats, Gigabytes, users, API calls)
"pricing":{
"price": {"USD":5} // Addon's pricing (Skip if applying catalog price) // Can also add discount block but coupons only appliicable at subscription level
}
}
],
"prorate": true // Will prorate the subscription thus far, and apply any credits to the difference being charged (or if downgrading, the credits are refunded as a partial order return)
}
]
}
{
"subscriptions": [
{
"subscription": "subscription-id",
"addons": [
{
"product": "existing-add-on-product-being-removed", // addon must be on the subscription
"quantity": 0
}
],
"prorate" : false // No proration (will only apply change in pricing from next period rebill)
}
]
}
Proration Preview
You can request a preview of prorated charges for a subscription that is eligible for proration. For a list of conditions when proration is not applicable, see Managing Active Subscriptions
To request a preview for a prorated subscription, use the example request shown below for an eligible subscription id.
{
"subscriptions": [
{
"subscription": "subscription-id", // Subscription ID to be updated (From Subscription detail page)
"prorate" : true, // If true the subscription is prorated upto the day of API call - any refunds are applied as credit to the remaining period
"preview" : true
}
]
}
Responses
See the following code snippets for examples of successful responses in case of a charge, or in case of a refund/credit
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "tbELUuXiSN-kDUcBIW6zIw",
"prorated": true,
"proration": {
"productPath": "add-on-subscription",
"currency": "USD",
"nextPeriodStartDate": "2022-11-01T00:00:00.000Z",
"nextPeriodEndDate": "2022-11-30T00:00:00.000Z",
"previousRemainingDays": 29.0,
"periodPastDays": 1.0,
"nextRemainingDays": 29.0,
"regularPeriod": {
"unit": "MONTH",
"unitCount": 1
},
"nextPricePerPeriod": {
"amount": 410.0,
"period": {
"count": 1,
"unit": "month"
}
},
"previousPricePerPeriod": {
"amount": 205.0,
"period": {
"count": 1,
"unit": "month"
}
},
"utilizedAmount": 6.83,
"creditAmount": 198.17,
"proratedAmount": 396.34,
"chargeAmount": 198.17
}
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "athBG1DPTFuOcw0iwPwi4A",
"prorated": true,
"proration": {
"productPath": "japan-sub",
"currency": "USD",
"nextPeriodStartDate": "2022-11-03T00:00:00.000Z",
"nextPeriodEndDate": "2022-11-09T00:00:00.000Z",
"previousRemainingDays": 30.0,
"periodPastDays": 0.0,
"nextRemainingDays": 7.0,
"regularPeriod": {
"unit": "WEEK",
"unitCount": 1
},
"nextPricePerPeriod": {
"amount": 10.0,
"period": {
"count": 1,
"unit": "week"
}
},
"previousPricePerPeriod": {
"amount": 100.0,
"period": {
"count": 1,
"unit": "month"
}
},
"utilizedAmount": 0.0,
"prorateAdjustment": 100.0,
"proratedAmount": 10.0,
"refundAmount": 90.0
}
}
]
}
Response Parameters
Parameter Name | Description |
---|---|
proratedAdjustment | Pertains to the old subscription item replaced or removed as part of a recent plan change This is the prorated price for the unused portion of the item |
proratedAmount | Pertains to the new subscription item added as part of a recent plan change Prorated price of the new item |
refundAmount | Amount credited to the customer for the unused portion of the changed item by issuing a refund |
utilizedAmount | Pertains to the old subscription item replaced or removed as part of the recent plan change This is the prorated amount for the used portion of the item |
Error Responses
{
"subscriptions": [
{
"action": "subscription.update",
"result": "error",
"subscription": "athBG1DPTFuOcw0iwPwi4A",
"prorated": false,
"proration": "Not currently supported"
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"subscription": "ZxMOne-aQ9qY3ykoamuJ-A",
"result": "error",
"error": {
"subscription.prorate": "Items not eligible for proration"
}
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"subscription": "ZxMOne-aQ9qY3ykoamuJ-A",
"result": "error",
"error": {
"subscription.prorate": "Unable to prorate"
}
}
]
}
Changing a subscription from automatic renewal to manual renewal
Use the Subscription POST
endpoint to switch auto renewed subscriptions to manual renew - where there are no payment details stored on file and requires the buyer to pay for each period manually.
{
"subscriptions": [
{
"subscription": "subscription-uuid-x",
"manualRenew": "true"
}
]
}
Set an end date and number of remaining periods for a subscription
You can use the /subscriptions
endpoint to programmatically adjust a subscription's end date or set a number of remaining periods, ensuring that the subscription doesn't renew beyond a point you determine.
To set an end date and the number of remaining periods, include the following parameters in your POST
request payload:
Parameter | Type | Required | Description |
---|---|---|---|
subscription | string | Yes | The unique identifier of the subscription you want to update. |
end | string | No | The subscription end date in YYYY-MM-DD format. If you pass a value into this field, it automatically sets isEndDateSet to true . |
isEndDateSet | boolean | Yes | Indicates whether the end date is set; must be true if end is also set. |
remainingPeriods | integer | No | The number of remaining periods before the subscription should end. Use as an alternative to specifying an end date. end takes precedence if both end and remainingPeriods are set. |
{
"subscriptions": [
{
"subscription": "tbELUuXiSN-kDUcBIW6zIw",
"end": "2024-07-19", // Sets the subscription end date to 19 July 2024
"isEndDateSet": true,
"remainingPeriods": 4 // Sets the remaining billing periods to 4
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "tbELUuXiSN-kDUcBIW6zIw"
}
]
}
Set a subscription to renew indefinitely
By setting remainingPeriods
to null
in a POST
request to the /subscriptions
endpoint, you can reverse any previously set end dates or remaining periods and make the subscription renew indefinitely.
{
"subscriptions": [
{
"subscription": "tbELUuXiSN-kDUcBIW6zIw",
"remainingPeriods": null
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "tbELUuXiSN-kDUcBIW6zIw"
}
]
}
Add or update a valid tax exemption ID
Add, update, or remove a valid tax exemption ID from an active subscription. Providing the ID will apply appropriate tax exemption rules.
{
"subscriptions": [
{
"subscription": "subscription-uuid-1", // Subscription ID to be updated (From Subscription detail page)
"taxExemptId": "tax-exempt-id", // Update a tax exempt ID
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "subscription-uuid-1"
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"subscription": "subscription-uuid-1",
"result": "error",
"error": {
"taxExemptId": "Tax Exempt ID is not valid"
}
}
]
}
Remove a tax exemption ID from a subscription
To remove a tax exemption ID from a subscription, send a blank string.
{
"subscriptions": [
{
"subscription": "subscription-uuid-1",
"taxExemptId": ""
}
]
}
{
"subscriptions": [
{
"action": "subscription.update",
"result": "success",
"subscription": "subscription-uuid-1"
}
]
}