Handle price changes & metered usage

If you operate a SaaS business, your pricing most likely varies depending on the usage of your service by your customers. Addons allow you to charge your customers per collaborator, website, or per API call to only name a few.


What are addons

Addons are additional elements your customers are be billed for at each billing cycles of the Subscription the addons are applied to. It is possible for a subscription to have several addons.

An addon is composed of several attributes used to compute the amount billed at each cycle:

  • amount is the base amount of the addon, which cannot be changed once the addon is added.
  • quantity is the amount multiplier used to compute the amount billed. For an amount of 2 and a quantity set to 10, the billed amount of the addon is 20. The quantity must be a positive number, or 0.
  • type is the type of the addon. The possible values are recurring and metered. The only difference is that metered addons will have their quantity field automatically reset to 0 at each billing cycle.

To apply an addon on a subscription, you can use Addons. It is only possible to apply a Plan on a subscription as an addon once (although a subscription can have multiple addons composed of several different plans).

Create a plan for our future addon

Let’s first create a plan that’ll be used as an addon on our future subscription. It is important to notice that the interval of the plan which will be used as an addon must be the same as the one of the subscription we’ll want to apply it to.

curl -X POST https://api.processout.com/plans \
    -u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8 \
    -d id="per-seat-addon" \
    -d name="Per seat addon" \
    -d amount="10.00" \
    -d currency=USD \
    -d interval=1m
var ProcessOut = require("processout");
var client = new ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8");

client.newPlan().create({
    id:       "per-seat-addon",
    name:     "Per seat addon",
    amount:   "10.00",
    interval: "1m"
}).then(function(plan) {
    //

}, function(err) {
    // An error occured

});
import processout
client = processout.ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

plan = client.new_plan().create({
    "id":       "per-seat-addon",
    "name":     "Per seat addon",
    "amount":   "10.00",
    "currency": "USD",
    "interval": "1m"
})
require "processout"
client = ProcessOut::Client.new(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

plan = client.plan.create(
    id:       "per-seat-addon",
    name:     "Per seat addon",
    amount:   "10.00",
    currency: "USD",
    interval: "1m"
)
<?php
$client = new \ProcessOut\ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8");

$plan = $client->newPlan()->create(array(
    "id"       => "per-seat-addon",
    "name"     => "Per seat addon",
    "amount"   => "10.00",
    "currency" => "USD",
    "interval" => "1m"
));
import "gopkg.in/processout.v4"
client := processout.New(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

plan, err := client.NewPlan().Create(&processout.PlanCreateParameters{
    Plan: &processout.Plan{
        ID:       processout.String("per-seat-addon"),
        Name:     processout.String("Per seat addon"),
        Amount:   processout.String("10.00"),
        Currency: processout.String("USD"),
        Interval: processout.String("1m"),
    },
})

Use the plan as an addon

Now that we’ve created the plan we want to use an addon, we just need to apply it to an already existing subscription.

When adding, updating or removing an addon, it is possible to prorate changes in order to correctly bill your customer for what’s been used of its plan, and for what’s to be billed in the future. Learn more about it here ↗. Prorating is disabled for metered addons.

curl -X POST https://api.processout.com/subscriptions/sub_7kAxfNML6jIc3bltGIt0uK2nKHDyzzq3/addons \
    -u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8 \
    -d plan_id="per-seat-addon" \
    -d quantity=2 \
    -d prorate=true
var ProcessOut = require("processout");
var client = new ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8");

client.newAddon().create({
    subscription_id: "sub_7kAxfNML6jIc3bltGIt0uK2nKHDyzzq3",
    plan_id:         "per-seat-addon",
    quantity:        2,

    prorate: true
});
addon = client.new_addon().create({
    "subscription_id": "sub_7kAxfNML6jIc3bltGIt0uK2nKHDyzzq3",
    "plan_id":         "per-seat-addon",
    "quantity":        2,

    "prorate": true
})
require "processout"
client = ProcessOut::Client.new(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

addon = client.addon.create(
    subscription_id: "sub_7kAxfNML6jIc3bltGIt0uK2nKHDyzzq3",
    plan_id:         "per-seat-addon",
    quantity:        2,

    prorate: true
)
<?php
$client = new \ProcessOut\ProcessOut(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8");

$addon = $client->newAddon()->create(array(
    "subscription_id" => "sub_7kAxfNML6jIc3bltGIt0uK2nKHDyzzq3",
    "plan_id"         => "per-seat-addon",
    "quantity"        => 2,

    "prorate" => true
));
import "gopkg.in/processout.v4"
client := processout.New(
    "test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x", 
    "key_sandbox_jqSPvwq3AG5MlYAgqxlwwgOcAC3Zy7d8")

addon, err := client.NewAddon().Create(&processout.AddonApplyParameters{
    Addon: &processout.Addon{
        SubscriptionID: "sub_7kAxfNML6jIc3bltGIt0uK2nKHDyzzq3",
        PlanID:         "per-seat-addon",
        Quantity:       2,
    },
    Prorate: true,
})