Getting started with importing subscription data via the API

Follow this tutorial to learn how to import billing data for up-to-date subscription data and real-time metrics in ChartMogul.

Overview

ChartMogul uses billing data to generate subscriptions and calculate metrics. Build an integration with the ChartMogul API to import billing data from multiple sources for up-to-date metrics in ChartMogul.

📘

Alternative import methods

Importing data using the API is the best method for businesses with developer resources. Learn more about non-programmatic import methods in Getting started with importing data for Subscription Analytics.

There are two steps to building an integration:

  1. Importing historical billing data
  2. Importing subscription updates

Importing historical billing data

To import your business’ existing data, create a data source. Use the source’s UUID you’ll receive in the response in subsequent API requests.

# Create a data source

curl -X POST "https://api.chartmogul.com/v1/data_sources" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{ 
            "name": "In-house billing"
         }'
# Create a data source

ChartMogul::DataSource.create!(
  name: "In-house billing",
)
// Create a data source

ChartMogul.DataSource.create(config, {
  name: "In-house billing",
});
// Create a data source

ChartMogul\DataSource::create([
  "name" => "In-house billing"
]);
// Create a data source

api.CreateDataSource("In-house billing")
# Create a data source

chartmogul.DataSource.create(config, data={"name": "In-house billing"})

Then, import customers, plans, invoices, line items, transactions, and subscription event objects using the Import Data in Bulk endpoint. This endpoint allows you to import multiple objects through a single API query and is recommended when importing more than 100 objects.

# Import data in bulk

curl -X POST "https://api.chartmogul.com/v1/data_sources/ds_SOURCE_UUID/json_imports" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
            "external_id": "ds_import_1",
            "customers": [
              {
                "external_id": "scus_0001",
                "name": "Andrew Jones",
                "email": "[email protected]",
                "country": "US",
                "state": "California",
                "city": "San Francisco",
                "zip": "90210",
                "company": "CA Printing Company",
                "lead_created_at": "2023-05-14 00:00:00",
                "free_trial_started_at": "2023-06-01 00:00:00"
              }
            ],
            "plans": [
              {
                "name": "Gold Biannual",
                "external_id": "gold_biannual",
                "interval_count": 6,
                "interval_unit": "month"
              }
            ],
            "invoices": [
              {
                "external_id": "inv_001",
                "date": "2023-04-02 21:37:00",
                "due_date": "2023-05-02 21:37:00",
                "currency": "USD",
                "customer_external_id": "scus_0001"
              },
              {
                "external_id": "inv_002",
                "date": "2023-05-02 21:37:00",
                "due_date": "2023-06-02 21:37:00",
                "currency": "USD",
                "customer_external_id": "scus_0001"
              },
              {
                "external_id": "inv_003",
                "date": "2023-06-02 21:37:00",
                "due_date": "2023-07-02 21:37:00",
                "currency": "USD",
                "customer_external_id": "scus_0001"
              }
            ],
            "line_items": [
              {
                "type": "subscription",
                "amount_in_cents": 1000,
                "quantity": 1,
                "invoice_external_id": "inv_001",
                "plan_external_id": "gold_biannual",
                "subscription_external_id": "sub_0001",
                "service_period_start": "2023-04-02 21:37:00",
                "service_period_end": "2023-05-02 21:37:00"
              },
              {
                "type": "subscription",
                "amount_in_cents": 1000,
                "quantity": 1,
                "invoice_external_id": "inv_002",
                "plan_external_id": "gold_biannual",
                "subscription_external_id": "sub_0001",
                "service_period_start": "2023-05-02 21:37:00",
                "service_period_end": "2023-06-02 21:37:00"
              },
              {
                "type": "subscription",
                "amount_in_cents": 1500,
                "quantity": 1,
                "invoice_external_id": "inv_003",
                "plan_external_id": "gold_biannual",
                "subscription_external_id": "sub_0001",
                "service_period_start": "2023-06-02 21:37:00",
                "service_period_end": "2023-07-02 21:37:00"
              }
            ],
            "transactions": [
              {
                "invoice_external_id": "inv_001",
                "external_id": "trans_0001",
                "type": "payments",
                "result": "successful",
                "date": "2023-04-02 21:37:00"
              },
              {
                "invoice_external_id": "inv_002",
                "external_id": "trans_0002",
                "type": "payment",
                "result": "failed",
                "date": "2023-05-02 21:37:00"
              },
              {
                "invoice_external_id": "inv_002",
                "external_id": "trans_0003",
                "type": "payment",
                "result": "successful",
                "date": "2005-05-03 21:37:00"
              },
              {
                "invoice_external_id": "inv_003",
                "external_id": "trans_0004",
                "type": "payment",
                "result": "successful",
                "date": "2023-06-03 21:37:00"
              }
            ],
            "subscription_events": [
              {
                "external_id": "scus_0001",
                "subscription_set_external_id": "sub_0001b",
                "subscription_external_id": "evnt_001",
                "customer_external_id": "scus_0001",
                "plan_external_id": "gold_biannual",
                "event_date": "2023-04-02 21:37:00",
                "effective_date": "2023-04-02 21:37:00",
                "event_type": "subscription_start",
                "currency": "USD",
                "amount_in_cents": 150000,
                "quantity": 1
              }
            ]
        }'

Once you’ve successfully completed the above steps, ChartMogul processes your data and generates metrics. Check your import status with the Track Import Status endpoint.

Next, keep new data from your billing system in sync with ChartMogul for up-to-date metrics.

📘

Non-programmatic ways to import data

In addition to the API, you can add subscription billing data to ChartMogul:

Importing subscription updates

Next, prepare your integration to keep ChartMogul updated with events from your billing system. You’ll use the customer and plan UUIDs generated when importing historical data. To retrieve all imported customer and plan objects along with their ChartMogul UUIDs, use the List Customers and List Plans endpoints.

Learn more about importing each type of subscription update:

New subscription

📘

New Business

When a non-paying customer purchases their first subscription, ChartMogul classifies the subscription MRR as New Business.

When a customer starts a new subscription in your billing system, import it to ChartMogul.

New subscribers

When a customer purchases their first subscription:

  1. Create the customer record using the Create a Customer endpoint.
# Create a customer

curl -X POST "https://api.chartmogul.com/v1/customers" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
            "data_source_uuid": "ds_SOURCE_UUID",
            "external_id": "scus_0002",
            "name": "Anna Lopez",
            "email": "[email protected]",
            "country": "US",
            "state": "New York",
            "city": "New York",
            "zip": "87123",
            "company": "Myriapod Labs"
        }'
# Create a customer

ChartMogul::Customer.create!(
  data_source_uuid: "ds_SOURCE_UUID",
  external_id: "scus_0002",
  name: "Anna Lopez",
  email: "[email protected]",
  country: "US",
  state: "New York",
  city: "New York",
  zip: "87123",
  company: "Myriapod Labs",
)
// Create a customer

ChartMogul.Customer.create(config, {
  data_source_uuid: "ds_SOURCE_UUID",
  external_id: "scus_0002",
  name: "Anna Lopez",
  email: "[email protected]",
  country: "US",
  state: "New York",
  city: "New York",
  zip: "87123",
  company: "Myriapod Labs",
});
// Create a customer

ChartMogul\Customer::create([
  "data_source_uuid" => "ds_SOURCE_UUID",
  "external_id" => "scus_0002",
  "name" => "Anna Lopez",
  "email" => "[email protected]",
  "country" => "US",
  "state" => "New York",
  "city" => "New York",
  "zip" => "87123",
  "company" => "Myriapod Labs"
]);
// Create a customer

api.CreateCustomer(&cm.NewCustomer{
  DataSourceUUID: "ds_SOURCE_UUID",
  ExternalID:     "scus_0002",
  Name:           "Anna Lopez",
  Email:          "[email protected]",
  Country:        "US",
  State:          "New York",
  City:           "New York",
  Zip:            "87123",
  Company:        "Myriapod Labs",
})
# Create a customer

chartmogul.Customer.create(
  config,
  data={
    "data_source_uuid": "ds_SOURCE_UUID",
    "external_id": "scus_0002",
    "name": "Anna Lopez",
    "email": "[email protected]",
    "country": "US",
    "state": "New York",
    "city": "New York",
    "zip": "87123",
    "company": "Myriapod Labs",
  },
)
  1. If the plan that the customer purchased does not exist in ChartMogul, create a new plan object using the Create a Plan endpoint.
# Create a plan

curl -X POST "https://api.chartmogul.com/v1/plans" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{ 
            "data_source_uuid": "ds_SOURCE_UUID",
            "name": "Silver Monthly",
            "interval_count": 1,
            "interval_unit": "month",
            "external_id": "silver_monthly"
        }'
# Create a plan

ChartMogul::Plan.create!(
  data_source_uuid: "ds_SOURCE_UUID",
  name: "Silver Monthly",
  interval_count: 1,
  interval_unit: "month",
  external_id: "silver_monthly",
)
// Create a plan

ChartMogul.Plan.create(config, {
  data_source_uuid: "ds_SOURCE_UUID",
  name: "Silver Monthly",
  interval_count: 1,
  interval_unit: "month",
  external_id: "silver_monthly",
});
// Create a plan

ChartMogul\Plan::create([
  "data_source_uuid" => "ds_SOURCE_UUID",
  "name" => "Silver Monthly",
  "interval_count" => 1,
  "interval_unit" => "month",
  "external_id" => "silver_monthly"
]);
// Create a plan

api.CreatePlan(&cm.Plan{
  DataSourceUUID: "ds_SOURCE_UUID",
  Name:           "Silver Monthly",
  IntervalCount:  1,
  IntervalUnit:   "month",
  ExternalID:     "silver_monthly",
})
# Create a plan

chartmogul.Plan.create(
  config,
  data={
    "data_source_uuid": "ds_SOURCE_UUID",
    "name": "Silver Monthly",
    "interval_count": 1,
    "interval_unit": "month",
    "external_id": "silver_monthly",
  },
)
  1. Import invoices for the new subscription using the Import Invoices endpoint.
# Import invoices

curl -X POST "https://api.chartmogul.com/v1/import/customers/cus_CUSTOMER_UUID/invoices" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
            "invoices": [
              {
                "external_id": "inv_004",
                "date": "2023-05-01 00:00:00",
                "currency": "USD",
                "due_date": "2023-05-15 00:00:00",
                "customer_external_id": "scus_0002",
                "data_source_uuid": "ds_SOURCE_UUID",
                "line_items": [
                  {
                    "type": "subscription",
                    "subscription_external_id": "sub_0002",
                    "plan_uuid":"pl_PLAN_UUID",
                    "service_period_start": "2023-05-01 00:00:00",
                    "service_period_end": "2023-06-01 00:00:00",
                    "amount_in_cents": 5000,
                    "quantity": 1,
                    "discount_code": "PSO86",
                    "discount_amount_in_cents": 1000,
                    "tax_amount_in_cents": 900
                  }
                ],
                "transactions": [
                  {
                    "date": "2023-05-05 00:14:23",
                    "type": "payment",
                    "result": "successful"
                  }
                ]   
              },
              {
                "external_id": "inv_005",
                "date": "2023-06-01 00:00:00",
                "currency": "USD",
                "due_date": "2023-06-15 00:00:00",
                "customer_external_id": "scus_0002",
                "data_source_uuid": "ds_SOURCE_UUID",
                "line_items": [
                  {
                    "type": "subscription",
                    "subscription_external_id": "sub_0002",
                    "plan_uuid":"pl_PLAN_UUID",
                    "service_period_start": "2023-06-01 00:00:00",
                    "service_period_end": "2023-07-01 00:00:00",
                    "amount_in_cents": 5000,
                    "quantity": 1,
                    "discount_code": "PSO86",
                    "discount_amount_in_cents": 1000,
                    "tax_amount_in_cents": 900
                  }
                ],
                "transactions": [
                  {
                    "date": "2023-06-05 07:54:02",
                    "type": "payment",
                    "result": "successful"
                  }
                ]   
              }
            ]
        }'
# Import invoices

line_item_1 = ChartMogul::LineItems::Subscription.new(
  subscription_external_id: "sub_0002",
  plan_uuid: "pl_PLAN_UUID",
  service_period_start: Time.utc(2023, 5, 1),
  service_period_end: Time.utc(2023, 6, 1),
  amount_in_cents: 5000,
  quantity: 1,
  discount_code: "PSO86",
  discount_amount_in_cents: 1000,
  tax_amount_in_cents: 900,
)

transaction_1 = ChartMogul::Transactions::Payment.new(
  date: Time.utc(2023, 5, 5, 0, 14, 23),
  result: "successful",
)

invoice_1 = ChartMogul::Invoice.new(
  external_id: "inv_004",
  date: Time.utc(2023, 5, 1),
  currency: "USD",
  due_date: Time.utc(2023, 5, 15),
  customer_external_id: "scus_0002",
  data_source_uuid: "ds_SOURCE_UUID",
  line_items: [line_item_1],
  transactions: [transaction_1],
)

line_item_2 = ChartMogul::LineItems::Subscription.new(
  subscription_external_id: "sub_0002",
  plan_uuid: "pl_PLAN_UUID",
  service_period_start: Time.utc(2023, 6, 1),
  service_period_end: Time.utc(2023, 7, 1),
  amount_in_cents: 5000,
  quantity: 1,
  discount_code: "PSO86",
  discount_amount_in_cents: 1000,
  tax_amount_in_cents: 900,
)

transaction_2 = ChartMogul::Transactions::Payment.new(
  date: Time.utc(2023, 6, 5, 7, 54, 02),
  result: "successful",
)

invoice_2 = ChartMogul::Invoice.new(
  external_id: "inv_005",
  date: Time.utc(2023, 6, 1),
  currency: "USD",
  due_date: Time.utc(2023, 6, 15),
  customer_external_id: "scus_0002",
  data_source_uuid: "ds_SOURCE_UUID",
  line_items: [line_item_2],
  transactions: [transaction_2],
)

ChartMogul::CustomerInvoices.create!(
  customer_uuid: "cus_CUSTOMER_UUID",
  invoices: [invoice_1, invoice_2],
)

// Import invoices

ChartMogul.Invoice.create(config, "cus_CUSTOMER_UUID", {
  invoices: [
    {
      external_id: "inv_004",
      date: "2023-05-01 00:00:00",
      currency: "USD",
      due_date: "2023-05-15 00:00:00",
      customer_external_id: "scus_0002",
      data_source_uuid: "ds_SOURCE_UUID",
      line_items: [
        {
          type: "subscription",
          subscription_external_id: "sub_0002",
          plan_uuid: "pl_PLAN_UUID",
          service_period_start: "2023-05-01 00:00:00",
          service_period_end: "2023-06-01 00:00:00",
          amount_in_cents: 5000,
          quantity: 1,
          discount_code: "PSO86",
          discount_amount_in_cents: 1000,
          tax_amount_in_cents: 900,
        },
      ],
      transactions: [
        {
          date: "2023-05-05 00:14:23",
          type: "payment",
          result: "successful",
        },
      ],
    },
    {
      external_id: "inv_005",
      date: "2023-06-01 00:00:00",
      currency: "USD",
      due_date: "2023-06-15 00:00:00",
      customer_external_id: "scus_0002",
      data_source_uuid: "ds_SOURCE_UUID",
      line_items: [
        {
          type: "subscription",
          subscription_external_id: "sub_0002",
          plan_uuid: "pl_PLAN_UUID",
          service_period_start: "2023-06-01 00:00:00",
          service_period_end: "2023-07-01 00:00:00",
          amount_in_cents: 5000,
          quantity: 1,
          discount_code: "PSO86",
          discount_amount_in_cents: 1000,
          tax_amount_in_cents: 900,
        },
      ],
      transactions: [
        {
          date: "2023-06-05 07:54:02",
          type: "payment",
          result: "successful",
        },
      ],
    },
  ],
});
// Import invoices

$line_item_1 = new ChartMogul\LineItems\Subscription([
  "subscription_external_id" => "sub_0002",
  "plan_uuid" => "pl_PLAN_UUID",
  "service_period_start" => "2023-05-01",
  "service_period_end" => "2023-06-01",
  "amount_in_cents" => 5000,
  "quantity" => 1,
  "discount_code" => "PSO86",
  "discount_amount_in_cents" => 1000,
  "tax_amount_in_cents" => 900
]);

$transaction_1 = new ChartMogul\Transactions\Payment([
  "date" => "2023-05-05",
  "result" => "successful"
]);

$invoice_1 = new ChartMogul\Invoice([
  "external_id" => "inv_004",
  "date" => "2023-05-01",
  "currency" => "USD",
  "due_date" => "2023-05-15",
  "customer_external_id" => "scus_0002",
  "data_source_uuid" => "ds_SOURCE_UUID",
  "line_items" => [$line_item_1],
  "transactions" => [$transaction_1]
]);

$line_item_2 = new ChartMogul\LineItems\Subscription([
  "subscription_external_id" => "sub_0002",
  "plan_uuid" => "pl_PLAN_UUID",
  "service_period_start" => "2023-06-01",
  "service_period_end" => "2023-07-01",
  "amount_in_cents" => 5000,
  "quantity" => 1,
  "discount_code" => "PSO86",
  "discount_amount_in_cents" => 1000,
  "tax_amount_in_cents" => 900
]);

$transaction_2 = new ChartMogul\Transactions\Payment([
  "date" => "2023-06-05",
  "result" => "successful"
]);

$invoice_2 = new ChartMogul\Invoice([
  "external_id" => "inv_005",
  "date" => "2023-06-01",
  "currency" => "USD",
  "due_date" => "2023-06-15",
  "customer_external_id" => "scus_0002",
  "data_source_uuid" => "ds_SOURCE_UUID",
  "line_items" => [$line_item_2],
  "transactions" => [$transaction_2]
]);

ChartMogul\CustomerInvoices::create([
  "customer_uuid" => "cus_CUSTOMER_UUID",
  "invoices" => [$invoice_1, $invoice_2]
]);
// Import invoices

lineItem1 := &cm.LineItem{
  SubscriptionExternalID: "sub_0002",
  PlanUUID:               "pl_PLAN_UUID",
  ServicePeriodStart:     "2023-05-01 00:00:00",
  ServicePeriodEnd:       "2023-06-01 00:00:00",
  AmountInCents:          5000,
  Quantity:               1,
  DiscountCode:           "PSO86",
  DiscountAmountInCents:  1000,
  TaxAmountInCents:       900,
  Type:                   "subscription",
}

transaction1 := &cm.Transaction{
  Date:   "2023-05-05 00:14:23",
  Type:   "payment",
  Result: "successful",
}

invoice1 := &cm.Invoice{
  ExternalID:         "inv_004",
  Date:               "2023-05-01 00:00:00",
  Currency:           "USD",
  DueDate:            "2023-05-15 00:00:00",
  CustomerExternalID: "scus_0002",
  DataSourceUUID:     "ds_SOURCE_UUID",
  LineItems:          []*cm.LineItem{lineItem1},
  Transactions:       []*cm.Transaction{transaction1},
}

lineItem2 := &cm.LineItem{
  SubscriptionExternalID: "sub_0002",
  PlanUUID:               "pl_PLAN_UUID",
  ServicePeriodStart:     "2023-06-01 00:00:00",
  ServicePeriodEnd:       "2023-07-01 00:00:00",
  AmountInCents:          5000,
  Quantity:               1,
  DiscountCode:           "PSO86",
  DiscountAmountInCents:  1000,
  TaxAmountInCents:       900,
  Type:                   "subscription",
}

transaction2 := &cm.Transaction{
  Date:   "2023-06-05 07:54:02",
  Type:   "payment",
  Result: "successful",
}

invoice2 := &cm.Invoice{
  ExternalID:         "inv_005",
  Date:               "2023-06-01 00:00:00",
  Currency:           "USD",
  DueDate:            "2023-06-15 00:00:00",
  CustomerExternalID: "scus_0002",
  DataSourceUUID:     "ds_SOURCE_UUID",
  LineItems:          []*cm.LineItem{lineItem2},
  Transactions:       []*cm.Transaction{transaction2},
}

api.CreateInvoices(
  []*cm.Invoice{invoice1, invoice2},
  "cus_CUSTOMER_UUID",
)
# Import invoices

chartmogul.Invoice.create(
  config,
  uuid="cus_CUSTOMER_UUID",
  data={
    "invoices": [
      {
        "external_id": "inv_004",
        "date": datetime(2023, 5, 1, 0, 0, 0),
        "currency": "USD",
        "due_date": datetime(2023, 5, 15, 0, 0, 0),
        "customer_external_id": "scus_0002",
        "data_source_uuid": "ds_SOURCE_UUID",
        "line_items": [
          {
            "type": "subscription",
            "subscription_external_id": "sub_0002",
            "plan_uuid": "pl_PLAN_UUID",
            "service_period_start": datetime(2023, 5, 1, 0, 0, 0),
            "service_period_end": datetime(2023, 6, 1, 0, 0, 0),
            "amount_in_cents": 5000,
            "quantity": 1,
            "discount_code": "PSO86",
            "discount_amount_in_cents": 1000,
            "tax_amount_in_cents": 900,
          }
        ],
        "transactions": [
          {
            "date": datetime(2023, 5, 5, 0, 14, 23),
            "type": "payment",
            "result": "successful",
          }
        ],
      },
      {
        "external_id": "inv_005",
        "date": datetime(2023, 6, 1, 0, 0, 0),
        "currency": "USD",
        "due_date": datetime(2023, 6, 15, 0, 0, 0),
        "customer_external_id": "scus_0002",
        "data_source_uuid": "ds_SOURCE_UUID",
        "line_items": [
          {
            "type": "subscription",
            "subscription_external_id": "sub_0002",
            "plan_uuid": "pl_PLAN_UUID",
            "service_period_start": datetime(2023, 6, 1, 0, 0, 0),
            "service_period_end": datetime(2023, 7, 1, 0, 0, 0),
            "amount_in_cents": 5000,
            "quantity": 1,
            "discount_code": "PSO86",
            "discount_amount_in_cents": 1000,
            "tax_amount_in_cents": 900,
          }
        ],
        "transactions": [
          {
            "date": datetime(2023, 6, 5, 7, 54, 2),
            "type": "payment",
            "result": "successful",
          }
        ],
      },
    ]
  },
)

Existing subscribers

When an existing subscriber purchases an additional subscription:

  1. If the plan doesn’t exist in ChartMogul, create it using the Create a Plan endpoint.
  2. Import an invoice for the purchase using the Import Invoices endpoint.

Subscription renewal

To import a renewal into ChartMogul, use the Import Invoices endpoint and reference the subscription_external_id of the subscription being renewed.

📘

How ChartMogul references the correct subscription

When an existing subscription_external_id is used in an invoice, ChartMogul renews or updates the existing subscription. When a new subscription_external_id is used in an invoice, ChartMogul generates a new subscription.
Use the List Customer’s Subscriptions endpoint to retrieve the subscription_external_id specified by you, the subscription_uuid generated by ChartMogul, and other basic subscription information.

📘

How ChartMogul handles renewals with late invoices

ChartMogul assumes good faith if renewal invoices (or payments for an invoice) are not received on time, and continues to report MRR for a subscription. To change a subscription’s status and reported MRR, you’ll need to explicitly cancel it. Alternatively, use the Handling Past-due Subscriptions setting to churn past-due subscriptions after a specified number of days.

📘

Reporting cash flow metrics in ChartMogul

To report cash flow metrics, import transaction data. Include failed transaction attempts for an invoice to enable reporting on failed charges.

Subscription update

📘

Expansion vs. Contraction

When a customer upgrades an existing subscription or purchases an additional subscription, ChartMogul classifies the net increase in subscription MRR as Expansion.
When a customer downgrades an existing subscription or cancels one or more (but not their last) subscription, ChartMogul classifies the net decrease in subscription MRR as Contraction.

To import a subscription update into ChartMogul, e.g. the plan changes, the price increases or decreases, or the discount amount changes, use the same subscription_external_id when importing invoices into ChartMogul.

Updates at the end of a previously invoiced service period

Create a new invoice for the subsequent service period using the Import Invoices endpoint and reference the subscription_external_id of the updated subscription. If the plan has been changed, then specify the UUID of the new plan as the plan_uuid in the invoice.

Updates in the middle of a service period

It’s common for businesses to charge customers a prorated amount for subscriptions that change in the middle of the service period.

In this case, import an invoice using the Import Invoices endpoint, with the attribute prorated set to true, and the prorated service_period_start and service_period_end timestamps, on the relevant subscription line item.

For detailed instructions on different prorated billing scenarios, read this tutorial.

Subscription cancellation

📘

Churn

When a customer cancels their last (or only) subscription, ChartMogul classifies the lost subscription MRR as Churn.

To import a cancellation into ChartMogul, use the Cancel a Customer’s Subscription endpoint. Reference the subscription by its UUID and set the cancelled_at timestamp for the date the subscription ended.

# Cancel a subscription

curl -X PATCH "https://api.chartmogul.com/v1/import/subscriptions/sub_SUBSCRIPTION_UUID" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{ 
            "cancelled_at": "2023-07-15 00:00:00"
        }'
# Cancel a subscription

customer = ChartMogul::Customer.retrieve("cus_CUSTOMER_UUID")

subscription = customer.subscriptions.find { |e| e.uuid == "sub_SUBSCRIPTION_UUID" }

subscription.cancel(Time.utc(2023, 7, 15))
// Cancel a subscription

ChartMogul.Subscription.cancel(config, "sub_SUBSCRIPTION_UUID", {
  cancelled_at: "2023-07-15 00:00:00",
});
// Cancel a subscription

$subscription = new ChartMogul\Subscription(["uuid" => "sub_SUBSCRIPTION_UUID"]);

$canceldate = "2023-07-15";

$subscription->cancel($canceldate);
// Cancel a subscription

api.CancelSubscription(
  "sub_SUBSCRIPTION_UUID",
  &cm.CancelSubscriptionParams{CancelledAt: "2023-07-15 00:00:00"},
)
# Cancel a subscription

chartmogul.Subscription.cancel(
  config,
  uuid="sub_SUBSCRIPTION_UUID",
  data={"cancelled_at": datetime(2023, 7, 15, 0, 0, 0)},
)

If this is a historical subscription that’s already been canceled, you can include the cancellation date on the invoice instead of making a separate API call. For example, if a churned customer had renewed each month for two months and then canceled their monthly subscription, you can use the Import Invoices endpoint and include a line item with the cancelled_at timestamp on the last invoice.

# Import invoices for a canceled subscription

curl -X POST "https://api.chartmogul.com/v1/import/customers/cus_CUSTOMER_UUID/invoices" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
            "invoices": [
              {
                "external_id": "inv_006",
                "date": "2023-05-01 00:00:00",
                "currency": "USD",
                "due_date": "2023-05-15 00:00:00",
                "customer_external_id": "scus_0002",
                "data_source_uuid": "ds_SOURCE_UUID",         
                "line_items": [
                  {
                    "type": "subscription",
                    "subscription_external_id": "sub_0003",
                    "plan_uuid":"pl_PLAN_UUID",
                    "service_period_start": "2023-05-01 00:00:00",
                    "service_period_end": "2023-06-01 00:00:00",
                    "amount_in_cents": 5000,
                    "quantity": 1,
                    "discount_code": "PSO86",
                    "discount_amount_in_cents": 1000,
                    "tax_amount_in_cents": 900
                  }
                ],
                "transactions": [
                  {
                    "date": "2023-05-05 00:14:23",
                    "type": "payment",
                    "result": "successful"
                  }
                ]   
              },
              {
                "external_id": "inv_007",
                "date": "2023-06-01 00:00:00",
                "currency": "USD",
                "due_date": "2023-06-15 00:00:00",
                "customer_external_id": "scus_0002",
                "data_source_uuid": "ds_SOURCE_UUID",
                "line_items": [
                  {
                    "type": "subscription",
                    "subscription_external_id": "sub_0003",
                    "plan_uuid":"pl_PLAN_UUID",
                    "service_period_start": "2023-06-01 00:00:00",
                    "service_period_end": "2023-07-01 00:00:00",
                    "amount_in_cents": 5000,
                    "quantity": 1,
                    "discount_code": "PSO86",
                    "discount_amount_in_cents": 1000,
                    "tax_amount_in_cents": 900,
                    "cancelled_at": "2023-07-02 00:00:00"
                  }
                ],
                "transactions": [
                  {
                    "date": "2023-06-05 07:54:02",
                    "type": "payment",
                    "result": "successful"
                  }
                ]   
              }
            ]
          }'
# Import invoices for a canceled subscription

line_item_1 = ChartMogul::LineItems::Subscription.new(
  subscription_external_id: "sub_0003",
  plan_uuid: "pl_PLAN_UUID",
  service_period_start: Time.utc(2023, 5, 1),
  service_period_end: Time.utc(2023, 6, 1),
  amount_in_cents: 5000,
  quantity: 1,
  discount_code: "PSO86",
  discount_amount_in_cents: 1000,
  tax_amount_in_cents: 900,
)

transaction_1 = ChartMogul::Transactions::Payment.new(
  date: Time.utc(2023, 5, 5, 0, 14, 23),
  result: "successful",
)

invoice_1 = ChartMogul::Invoice.new(
  external_id: "inv_006",
  date: Time.utc(2023, 5, 1),
  currency: "USD",
  due_date: Time.utc(2023, 5, 15),
  customer_external_id: "scus_0002",
  data_source_uuid: "ds_SOURCE_UUID",
  line_items: [line_item_1],
  transactions: [transaction_1],
)

line_item_2 = ChartMogul::LineItems::Subscription.new(
  subscription_external_id: "sub_0003",
  plan_uuid: "pl_PLAN_UUID",
  service_period_start: Time.utc(2023, 6, 1),
  service_period_end: Time.utc(2023, 7, 1),
  amount_in_cents: 5000,
  quantity: 1,
  discount_code: "PSO86",
  discount_amount_in_cents: 1000,
  tax_amount_in_cents: 900,
  cancelled_at: Time.utc(2023, 7, 2),
)


transaction_2 = ChartMogul::Transactions::Payment.new(
  date: Time.utc(2023, 6, 5, 7, 54, 02),
  result: "successful",
)

invoice_2 = ChartMogul::Invoice.new(
  external_id: "inv_007",
  date: Time.utc(2023, 6, 1),
  currency: "USD",
  due_date: Time.utc(2023, 6, 15),
  customer_external_id: "scus_0003",
  data_source_uuid: "ds_SOURCE_UUID",
  line_items: [line_item_2],
  transactions: [transaction_2],
)

ChartMogul::CustomerInvoices.create!(
  customer_uuid: "cus_CUSTOMER_UUID",
  invoices: [invoice_1, invoice_2],
)

// Import invoices for a canceled subscription

ChartMogul.Invoice.create(config, "cus_CUSTOMER_UUID", {
  invoices: [
    {
      external_id: "inv_006",
      date: "2023-05-01 00:00:00",
      currency: "USD",
      due_date: "2023-05-15 00:00:00",
      customer_external_id: "scus_0002",
      data_source_uuid: "ds_SOURCE_UUID",
      line_items: [
        {
          type: "subscription",
          subscription_external_id: "sub_0003",
          plan_uuid: "pl_PLAN_UUID",
          service_period_start: "2023-05-01 00:00:00",
          service_period_end: "2023-06-01 00:00:00",
          amount_in_cents: 5000,
          quantity: 1,
          discount_code: "PSO86",
          discount_amount_in_cents: 1000,
          tax_amount_in_cents: 900,
        },
      ],
      transactions: [
        {
          date: "2023-05-05 00:14:23",
          type: "payment",
          result: "successful",
        },
      ],
    },
    {
      external_id: "inv_007",
      date: "2023-06-01 00:00:00",
      currency: "USD",
      due_date: "2023-06-15 00:00:00",
      customer_external_id: "scus_0002",
      data_source_uuid: "ds_SOURCE_UUID",
      line_items: [
        {
          type: "subscription",
          subscription_external_id: "sub_0003",
          plan_uuid: "pl_PLAN_UUID",
          service_period_start: "2023-06-01 00:00:00",
          service_period_end: "2023-07-01 00:00:00",
          amount_in_cents: 5000,
          quantity: 1,
          discount_code: "PSO86",
          discount_amount_in_cents: 1000,
          tax_amount_in_cents: 900,
          cancelled_at: "2023-07-02 00:00:00",
        },
      ],
      transactions: [
        {
          date: "2023-06-05 07:54:02",
          type: "payment",
          result: "successful",
        },
      ],
    },
  ],
});
// Import invoices for a canceled subscription

$line_item_1 = new ChartMogul\LineItems\Subscription([
  "subscription_external_id" => "sub_0003",
  "plan_uuid" => "pl_PLAN_UUID",
  "service_period_start" => "2023-05-01",
  "service_period_end" => "2023-06-01",
  "amount_in_cents" => 5000,
  "quantity" => 1,
  "discount_code" => "PSO86",
  "discount_amount_in_cents" => 1000,
  "tax_amount_in_cents" => 900
]);

$transaction_1 = new ChartMogul\Transactions\Payment([
  "date" => "2023-05-05",
  "result" => "successful"
]);

$invoice_1 = new ChartMogul\Invoice([
  "external_id" => "inv_006",
  "date" => "2023-05-01",
  "currency" => "USD",
  "due_date" => "2023-05-15",
  "customer_external_id" => "scus_0002",
  "data_source_uuid" => "ds_SOURCE_UUID",
  "line_items" => [$line_item_1],
  "transactions" => [$transaction_1]
]);

$line_item_2 = new ChartMogul\LineItems\Subscription([
  "subscription_external_id" => "sub_0003",
  "plan_uuid" => "pl_PLAN_UUID",
  "service_period_start" => "2023-06-01",
  "service_period_end" => "2023-07-01",
  "amount_in_cents" => 5000,
  "quantity" => 1,
  "discount_code" => "PSO86",
  "discount_amount_in_cents" => 1000,
  "tax_amount_in_cents" => 900,
  "cancelled_at" => "2023-07-02"
]);

$transaction_2 = new ChartMogul\Transactions\Payment([
  "date" => "2023-06-05",
  "result" => "successful"
]);

$invoice_2 = new ChartMogul\Invoice([
  "external_id" => "inv_007",
  "date" => "2023-06-01",
  "currency" => "USD",
  "due_date" => "2023-06-15",
  "customer_external_id" => "scus_0002",
  "data_source_uuid" => "ds_SOURCE_UUID",
  "line_items" => [$line_item_2],
  "transactions" => [$transaction_2]
]);

ChartMogul\CustomerInvoices::create([
  "customer_uuid" => "cus_CUSTOMER_UUID",
  "invoices" => [$invoice_1, $invoice_2]
]);
// Import invoices for a canceled subscription

lineItem1 := &cm.LineItem{
  SubscriptionExternalID: "sub_0003",
  PlanUUID:               "pl_PLAN_UUID",
  ServicePeriodStart:     "2023-05-01 00:00:00",
  ServicePeriodEnd:       "2023-06-01 00:00:00",
  AmountInCents:          5000,
  Quantity:               1,
  DiscountCode:           "PSO86",
  DiscountAmountInCents:  1000,
  TaxAmountInCents:       900,
  Type:                   "subscription",
}

transaction1 := &cm.Transaction{
  Date:   "2023-05-05 00:14:23",
  Type:   "payment",
  Result: "successful",
}

invoice1 := &cm.Invoice{
  ExternalID:         "inv_006",
  Date:               "2023-05-01 00:00:00",
  Currency:           "USD",
  DueDate:            "2023-05-15 00:00:00",
  CustomerExternalID: "scus_0002",
  DataSourceUUID:     "ds_SOURCE_UUID",
  LineItems:          []*cm.LineItem{lineItem1},
  Transactions:       []*cm.Transaction{transaction1},
}

lineItem2 := &cm.LineItem{
  SubscriptionExternalID: "sub_0003",
  PlanUUID:               "pl_PLAN_UUID",
  ServicePeriodStart:     "2023-06-01 00:00:00",
  ServicePeriodEnd:       "2023-07-01 00:00:00",
  AmountInCents:          5000,
  Quantity:               1,
  DiscountCode:           "PSO86",
  DiscountAmountInCents:  1000,
  TaxAmountInCents:       900,
  Type:                   "subscription",
  CancelledAt:            "2023-07-02 00:00:00",
}

transaction2 := &cm.Transaction{
  Date:   "2023-06-05 07:54:02",
  Type:   "payment",
  Result: "successful",
}

invoice2 := &cm.Invoice{
  ExternalID:         "inv_007",
  Date:               "2023-06-01 00:00:00",
  Currency:           "USD",
  DueDate:            "2023-06-15 00:00:00",
  CustomerExternalID: "scus_0002",
  DataSourceUUID:     "ds_SOURCE_UUID",
  LineItems:          []*cm.LineItem{lineItem2},
  Transactions:       []*cm.Transaction{transaction2},
}

api.CreateInvoices(
  []*cm.Invoice{invoice1, invoice2},
  "cus_CUSTOMER_UUID",
)
# Import invoices for a canceled subscription

chartmogul.Invoice.create(
  config,
  uuid="cus_CUSTOMER_UUID",
  data={
    "invoices": [
      {
        "external_id": "inv_006",
        "date": datetime(2023, 5, 1, 0, 0, 0),
        "currency": "USD",
        "due_date": datetime(2023, 5, 15, 0, 0, 0),
        "customer_external_id": "scus_0002",
        "data_source_uuid": "ds_SOURCE_UUID",
        "line_items": [
          {
            "type": "subscription",
            "subscription_external_id": "sub_0003",
            "plan_uuid": "pl_PLAN_UUID",
            "service_period_start": datetime(2023, 5, 1, 0, 0, 0),
            "service_period_end": datetime(2023, 6, 1, 0, 0, 0),
            "amount_in_cents": 5000,
            "quantity": 1,
            "discount_code": "PSO86",
            "discount_amount_in_cents": 1000,
            "tax_amount_in_cents": 900,
          }
        ],
        "transactions": [
          {
            "date": datetime(2023, 5, 5, 0, 14, 23),
            "type": "payment",
            "result": "successful",
          }
        ],
      },
      {
        "external_id": "inv_007",
        "date": datetime(2023, 6, 1, 0, 0, 0),
        "currency": "USD",
        "due_date": datetime(2023, 6, 15, 0, 0, 0),
        "customer_external_id": "scus_0002",
        "data_source_uuid": "ds_SOURCE_UUID",
        "line_items": [
          {
            "type": "subscription",
            "subscription_external_id": "sub_0003",
            "plan_uuid": "pl_PLAN_UUID",
            "service_period_start": datetime(2023, 6, 1, 0, 0, 0),
            "service_period_end": datetime(2023, 7, 1, 0, 0, 0),
            "amount_in_cents": 5000,
            "quantity": 1,
            "discount_code": "PSO86",
            "discount_amount_in_cents": 1000,
            "tax_amount_in_cents": 900,
            "cancelled_at": datetime(2023, 7, 2, 0, 0, 0),
          }
        ],
        "transactions": [
          {
            "date": datetime(2023, 6, 5, 7, 54, 2),
            "type": "payment",
            "result": "successful",
          }
        ],
      },
    ]
  },
)

Subscription reactivation

📘

Reactivation

When a formerly paying customer (who had previously churned) moves back onto a paid plan, ChartMogul classifies the new subscription MRR as Reactivation.

To import a reactivation into ChartMogul, use the Import Invoices endpoint and reference the subscription_external_id of the previously canceled subscription.

Once you complete the steps above, your integration is finished and ChartMogul keeps your subscription data and analytics updated in real time.

📘

Support

Don’t see your business use case covered here? Have questions regarding our API? Contact our support team.