• Content

Managing Subscriptions with Recurly API

Overview

In this guide we’ll walk through various methods for managing existing subscriptions programmatically via Recurly API. The following use cases will be covered:

  • Upgrading and Downgrading Subscriptions
  • Postponing Subscriptions
  • Pausing Subscriptions
  • Expiring Subscriptions

To get the most out of this guide, it’s recommended that you take a look at our product documentation for Subscription Changes, and also review the Quickstart Guide and the Purchases Guide.

Estimated Completion time

1 Hour

Upgrading and Downgrading

Subscription upgrades and downgrades involve modifications to the subscriptions’ plan, quantity, price, or included add-ons.

The Create Subscription Change endpoint is used to complete all of the upgrade and downgrade actions. You can specify the timeframe that you’d like the upgrade or downgrade to take place. You can opt for the change to occur immediately, when the subscription is next billed, or when the subscription term ends.

Change the subscription plan

To change the subscription plan, pass in the plan_id or plan_code of the new plan. In the example below, we’ll upgrade a customer’s existing subscription to a better plan, effective immediately:

Ruby

Node.js

Python

Java

Dotnet

PHP

change = @client.create_subscription_change(
  subscription_id: subscription_id,
  body: {
    timeframe: "now",
    plan_code: new_plan_code
  }
)
puts "Created subscription change: #{change.id}"
const subscriptionChangeCreate = {
  timeframe: 'now',
  planCode: newPlanCode
}

const change = await client.createSubscriptionChange(subscriptionId, subscriptionChangeCreate)
console.log('Created subscription change: ', change.id)
sub_change_create = {
  timeframe: "now",
  plan_code: new_plan_code
}
change = client.create_subscription_change(subscription_id, sub_change_create)
print("Created subscription change: %s" % change.id)
SubscriptionChangeCreate changeCreate = new SubscriptionChangeCreate();

changeCreate.setTimeframe("now");
changeCreate.setPlanCode(newPlanCode);

SubscriptionChange change = client.createSubscriptionChange(subscriptionId, changeCreate);
System.out.println("Created subscription change: " + change.getId());
var changeReq = new SubscriptionChangeCreate()
{
    Timeframe = "now",
    PlanCode = newPlanCode
};
SubscriptionChange change = client.CreateSubscriptionChange(subscriptionId, changeReq);
Console.WriteLine($"Created subscription change: {change.Id}");
}
$change_create = array(
    "timeframe" => "term_end",
    "plan_code" => $new_plan_code
);
$change = $client->createSubscriptionChange($subscription_id, $change_create);
echo "Created subscription change: {$change->getId()}" . PHP_EOL;


Change the subscription price

To change the subscription price, pass in a new unit_amount for the subscription. This will override the plan’s default unit amount. In the example below, we’ll increase the cost of the subscription to $20 once the current subscription term reaches its end (trimeframe=term_end):

Ruby

Node.js

Python

Java

Dotnet

PHP

change = @client.create_subscription_change(
  subscription_id: subscription_id,
  body: {
    timeframe: "term_end",
    unit_amount: 20
  }
)
puts "Created subscription change: #{change.id}"
const subscriptionChangeCreate = {
  timeframe: 'term_end',
  unit_amount: 20
}

const change = await client.createSubscriptionChange(subscriptionId, subscriptionChangeCreate)
console.log('Created subscription change: ', change.id)
sub_change_create = {
  timeframe: "term_end",
  unit_amount: 20
}
change = client.create_subscription_change(subscription_id, sub_change_create)
print("Created subscription change: %s" % change.id)
SubscriptionChangeCreate changeCreate = new SubscriptionChangeCreate();

changeCreate.setTimeframe("term_end");
changeCreate.setUnitAmount(20);

SubscriptionChange change = client.createSubscriptionChange(subscriptionId, changeCreate);
System.out.println("Created subscription change: " + change.getId());
var changeReq = new SubscriptionChangeCreate()
{
    Timeframe = "term_end",
    UnitAmount = 20
};
SubscriptionChange change = client.CreateSubscriptionChange(subscriptionId, changeReq);
Console.WriteLine($"Created subscription change: {change.Id}");
$change_create = array(
    "timeframe" => "term_end",
    "unit_amount" => 20
);
$change = $client->createSubscriptionChange($subscription_id, $change_create);
echo "Created subscription change: {$change->getId()}" . PHP_EOL;

Managing Add-Ons

Take a look at the Subscription Add-Ons guide for information about how to manage Subscription Add-Ons.

Postponing

Subscription postponement involves changes to your customer’s billing cycle (e.g. changing the date when your customer is next billed). Take a look at the product documentaton to learn more about this feature.

To postpone a subscription with Recurly API, use the Modify Subscription endpoint. In the example below, we’ll modify the date when the next billing period will start. This is particularly useful if you want to modify a subscription in a trial period (e.g. extend, or shorten the trial):

Ruby

Node.js

Python

Java

Dotnet

PHP

subscription = @client.modify_subscription(
  subscription_id: subscription_id,
  body: {
    next_bill_date: "2025-12-05"
  }
)
puts "Postponed Subscription #{subscription.uuid}"
const subscriptionChangeCreate = {
  timeframe: 'term_end',
  next_bill_date: '2025-12-05'
}

const change = await client.modifySubscription(subscriptionId, subscriptionChangeCreate)
console.log('Postponed subscription: ', change.uuid)
sub_change_create = {next_bill_date: "2025-12-05", timeframe: "term_end"}
change = client.modify_subscription(subscription_id, sub_change_create)
print("Postponed subscription: %s" % change.uuid)
final SubscriptionUpdate subUpdate = new SubscriptionUpdate();
subUpdate.setNextBillDate("2025-12-05");
final Subscription subscription = client.modifySubscription(subscriptionId, subUpdate);
System.out.println("Postponed subscription: " + subscription.getUuid());
var updateReq = new SubscriptionUpdate()
{
    NextBillDate = "2025-12-05"
};
Subscription subscription = client.ModifySubscription(subscriptionId, updateReq);
Console.WriteLine($"Postponed subscription: {subscription.Uuid}");
$update_req = array(
    "next_bill_date" => "2025-12-05"
);

$subscription = $client->modifySubscription($subscription_id, $update_req);
echo "Postponed subscription: {$change->getUuid()}" . PHP_EOL;

There are several other modification options available to you with this endpoint (e.g. changing the number of remaining billing cycles in the current term, or modifying the number of renewal billing cycles). Take a look at the reference documentation for more information.

Pausing

With Recurly API, pausing a subscription is easy and it’s a great way to give your customers an alternative to outright cancellation. Take a look at our product docs for more info on this feature.

To pause a subscription, you’ll use the Pause Subscription endpoint which provides the ability to freeze billing for a specified number of cycles at the next renewal date. Take a look at the example below where we pause a subscription for ten billing cycles:

Ruby

Node.js

Python

Java

Dotnet

PHP

sub = @client.pause_subscription(
  subscription_id: subscription_id,
  body: {
    remaining_pause_cycles: 10
  }
)
puts "Paused subscription: #{sub.uuid}"
const subscriptionPause = {
  remaining_pause_cycles: 10
}

const sub = await client.pauseSubscription(subscriptionId, subscriptionPause)
console.log('Paused subscription: ', sub.uuid)
sub_pause = {remaining_pause_cycles: 10}
sub = client.pause_subscription(subscription_id, sub_pause)
print("Paused subscription: %s" % sub.uuid)
final SubscriptionPause subPause = new SubscriptionPause();
subPause.setRemainingPauseCycles(10);

final Subscription sub = client.pauseSubscription(subscriptionId, subPause);
System.out.println("Paused subscription: " + sub.getUuid());
var pauseSubReq = new SubscriptionPause()
{
    RemainingPauseCycles = 10
};
Subscription sub = client.PauseSubscription(subscriptionId, pauseSubReq);
Console.WriteLine($"Paused subscription {sub.Uuid}");
$pause_sub_req = array(
    "remaining_pause_cycles" => 10
);

$sub = $client->pauseSubscription($subscription_id, $pause_sub_req);
echo "Paused subscription: {$sub->getUuid()}" . PHP_EOL;

Expired, cancelled, or failed subscriptions cannot be paused.

Expiring

A subscription is marked as expired as a result of a cancellation (e.g. customer ends their subscription at the next bill date or term) or termination (e.g. the subscription is ended in the middle of the billing cycle). Check out our product documentation for more details.

Termination

To terminate a subscription, call the Terminate Subscription endpoint and pass in the ID of the subscription to terminate. You may also specify a type of refund (full, partial, or none). In the example below, we’ll terminate a subscription and provide a partial refund to the customer:

Ruby

Node.js

Python

Java

Dotnet

PHP

sub = @client.terminate_subscription(
  subscription_id: subscription_id,
  body: {
    refund: "partial"
  }
)
puts "Terminated subscription: #{sub.uuid}"
terminateParams = { refund: "partial" }
const sub = await client.terminateSubscription(subscriptionId, terminateParams)
console.log('Terminated subscription: ', sub.uuid)
terminate_params = { refund: "partial" }
sub = client.terminate_subscription(subscription_id, terminate_params)
print("Terminated subscription: %s" % sub)
QueryParams queryParams = new QueryParams();
queryParams.setRefund("partial");
final Subscription sub = client.terminateSubscription(subscriptionId, queryParams);
System.out.println("Terminated subscription: " + sub.uuid());
Subscription sub = client.TerminateSubscription(subscriptionId, "partial");
Console.WriteLine($"Terminated subscription: {sub.Uuid}");
$terminate_sub_req = array(
    "refund" => "partial"
);

$sub = $client->terminateSubscription($subscription_id, $terminate_sub_req);
echo "Terminated subscription: {$sub->getUuid()}" . PHP_EOL;

A terminated subscription is immediately expired and cannot be reactivated.

Cancellation

To cancel a subscription, use the Cancel Subscription endpoint. Similar to termination, you’ll specify the ID of the subscription to cancel, but you’ll also specify if the subscription should end at the next billing date, or at the end of the term. In the example below, we’ll cancel a subscription at the end of the term:

Ruby

Node.js

Python

Java

Dotnet

PHP

subscription = @client.cancel_subscription(
  subscription_id: subscription_id
  body: {
    timeframe: "term_end"
  }
)
puts "Canceled subscription #{subscription.uuid}"
const subCancel = {
  timeframe: "term_end"
}
let expiredSub = await client.cancelSubscription(subscriptionId, subCancel)
console.log('Canceled subscription: ', expiredSub.uuid)
sub_cancel = {
  timeframe: "term_end"
}
subscription = client.cancel_subscription(subscription_id, sub_cancel)
print("Canceled subscription: %s" % subscription.uuid)
subCancel = new SubscriptionCancel()
subCancel.setTimeFrame("term_end")
final Subscription subscription = client.cancelSubscription(subscriptionId, subCancel);
System.out.println("Canceled subscription: " + subscription.getUuid());
var subCancel = new SubscriptionCancel()
{
    Timeframe = "term_end"
};
Subscription subscription = client.CancelSubscription(subscriptionId, subCancel);
Console.WriteLine($"Canceled subscription: {subscription.Uuid}");
$sub_cancel = array(
    "timeframe" => "term_end"
);

$subscription = $client->cancelSubscription($subscription_id, $sub_cancel);
echo "Canceled subscription: {$change->getUuid()}" . PHP_EOL;

At the end of the specified timeframe, the subscription will move to an expired state. However, it is possible to reactivate the subscription before that time using the Reactivate Subscription endpoint, which will restore the subscription back to it’s previous state. This is useful if your customer changes their mind and wants to continue with the service.

Next Steps

The examples presented in this guide are only the tip of the iceberg when it comes to managing subscriptions via Recurly API. Take a look at the full reference documentation, and never hesitate to reach out to our support team.