Tracking free subscriptions

This tutorial describes how to track free and freemium subscriptions in ChartMogul using the API.

If your product has a free plan or freemium tier, ChartMogul allows you to track those subscriptions the same way you track paid plans.

To create a free subscription:

  1. Create a plan for your free subscription
  2. Create an invoice with a zero-value line item

Use this method to add a free subscription to any customer in a Stripe, Chargebee, Recurly, Braintree, Google Play, App Store Connect, SaaSync or custom source.

If your customers are in a source outside this list, create a custom source. Within it, create customers with free subscriptions. Then merge those customers with the corresponding customers from your existing source.

Gradual rollout. We introduced the ability to track free subscriptions on October 2, 2025, and are making it gradually available to all accounts. If you can see the All Subscriptions chart in the app, it means you can track free subscriptions.

Creating a free plan

For deeper segmentation with plan filters, create a free plan using the Create a Plan endpoint:

curl -X POST "https://api.chartmogul.com/v1/plans" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
           "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
           "name": "Free",
           "interval_count": 1,
           "interval_unit": "month",
           "external_id": "plan_free"
         }'
ChartMogul::Import::Plan.create!(
  data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  name: "Free",
  interval_count: 1,
  interval_unit: "month",
  external_id: "plan_free",
)
ChartMogul.Plan.create(config, {
  data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  name: "Free",
  interval_count: 1,
  interval_unit: "month",
  external_id: "plan_free",
});
ChartMogul\Import\Plan::create([
  "data_source_uuid" => "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  "name" => "Free",
  "interval_count" => 1,
  "interval_unit" => "month",
  "external_id" => "plan_free"
]);
api.CreatePlan(&cm.Plan{
  DataSourceUUID: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  Name:           "Free",
  IntervalCount:  1,
  IntervalUnit:   "month",
  ExternalID:     "plan_free",
})
chartmogul.Plan.create(
  config,
  data={
    "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
    "name": "Free",
    "interval_count": 1,
    "interval_unit": "month",
    "external_id": "plan_free",
  },
)

Use the plan_uuid from the response when creating free subscription invoices.

Creating a free subscription invoice

Use the Import Invoices endpoint to create an invoice with a zero-value subscription line item:

If the customer belongs to a Stripe, Chargebee, Recurly, Braintree, Google Play, App Store Connect or SaaSync source, set the handle_as_user_edit query parameter to true. Without it, the invoice may be deleted during a resync or reimport. This is not required for custom sources. Learn more.

curl -X POST "https://api.chartmogul.com/v1/import/customers/cus_f466e33d-ff2b-4a11-8f85-417eb02157a7/invoices" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
            "invoices": [
              {
                "external_id": "inv_5b3e9c72",
                "date": "2026-01-10",
                "currency": "USD",
                "customer_external_id": "cus_7f9e2a41",
                "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
                "line_items": [
                  {
                    "type": "subscription",
                    "subscription_external_id": "sub_8c3f1b92",
                    "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
                    "service_period_start": "2026-01-10",
                    "amount_in_cents": 0,
                    "quantity": 1
                  }
                ]
              }
            ]
        }'
line_item = ChartMogul::LineItems::Subscription.new(
  subscription_external_id: "sub_8c3f1b92",
  plan_uuid: "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
  service_period_start: Time.utc(2026, 1, 10),
  amount_in_cents: 0,
  quantity: 1,
)

invoice = ChartMogul::Invoice.new(
  external_id: "inv_5b3e9c72",
  date: Time.utc(2026, 1, 10),
  currency: "USD",
  customer_external_id: "cus_7f9e2a41",
  data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  line_items: [line_item],
)

ChartMogul::CustomerInvoices.create!(
  customer_uuid: "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  invoices: [invoice],
)
ChartMogul.Invoice.create(config, "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7", {
  invoices: [
    {
      external_id: "inv_5b3e9c72",
      date: "2026-01-10",
      currency: "USD",
      customer_external_id: "cus_7f9e2a41",
      data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
      line_items: [
        {
          type: "subscription",
          subscription_external_id: "sub_8c3f1b92",
          plan_uuid: "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
          service_period_start: "2026-01-10",
          amount_in_cents: 0,
          quantity: 1,
        },
      ],
    },
  ],
});
$line_item = new ChartMogul\LineItems\Subscription([
  "subscription_external_id" => "sub_8c3f1b92",
  "plan_uuid" => "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
  "service_period_start" => "2026-01-10",
  "amount_in_cents" => 0,
  "quantity" => 1
]);

$invoice = new ChartMogul\Invoice([
  "external_id" => "inv_5b3e9c72",
  "date" => "2026-01-10",
  "currency" => "USD",
  "customer_external_id" => "cus_7f9e2a41",
  "data_source_uuid" => "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  "line_items" => [$line_item]
]);

ChartMogul\CustomerInvoices::create([
  "customer_uuid" => "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  "invoices" => [$invoice]
]);
lineItem := &cm.LineItem{
  Type:                   "subscription",
  SubscriptionExternalID: "sub_8c3f1b92",
  PlanUUID:               "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
  ServicePeriodStart:     "2026-01-10",
  AmountInCents:          0,
  Quantity:               1,
}

invoice := &cm.Invoice{
  ExternalID:         "inv_5b3e9c72",
  Date:               "2026-01-10",
  Currency:           "USD",
  CustomerExternalID: "cus_7f9e2a41",
  DataSourceUUID:     "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  LineItems:          []*cm.LineItem{lineItem},
}

api.CreateInvoices(
  []*cm.Invoice{invoice},
  "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
)
chartmogul.Invoice.create(
  config,
  uuid="cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  data={
    "invoices": [
      {
        "external_id": "inv_5b3e9c72",
        "date": datetime(2026, 1, 10),
        "currency": "USD",
        "customer_external_id": "cus_7f9e2a41",
        "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
        "line_items": [
          {
            "type": "subscription",
            "subscription_external_id": "sub_8c3f1b92",
            "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
            "service_period_start": datetime(2026, 1, 10),
            "amount_in_cents": 0,
            "quantity": 1,
          }
        ],
      }
    ]
  },
)

Upgrading to a paid plan

When the customer upgrades to a paid plan, use the Import Invoices endpoint to create a paid invoice:

curl -X POST "https://api.chartmogul.com/v1/import/customers/cus_f466e33d-ff2b-4a11-8f85-417eb02157a7/invoices" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
            "invoices": [
              {
                "external_id": "inv_1d8f4e61",
                "date": "2026-02-10",
                "currency": "USD",
                "customer_external_id": "cus_7f9e2a41",
                "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
                "line_items": [
                  {
                    "type": "subscription",
                    "subscription_external_id": "sub_8c3f1b92",
                    "plan_uuid": "pl_aab05d54-75b4-431b-adb2-eb6b9e543207",
                    "service_period_start": "2026-02-10",
                    "service_period_end": "2026-03-10",
                    "amount_in_cents": 5000,
                    "quantity": 1
                  }
                ]
              }
            ]
        }'
line_item = ChartMogul::LineItems::Subscription.new(
  subscription_external_id: "sub_8c3f1b92",
  plan_uuid: "pl_aab05d54-75b4-431b-adb2-eb6b9e543207",
  service_period_start: Time.utc(2026, 2, 10),
  service_period_end: Time.utc(2026, 3, 10),
  amount_in_cents: 5000,
  quantity: 1,
)

invoice = ChartMogul::Invoice.new(
  external_id: "inv_1d8f4e61",
  date: Time.utc(2026, 2, 10),
  currency: "USD",
  customer_external_id: "cus_7f9e2a41",
  data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  line_items: [line_item],
)

ChartMogul::CustomerInvoices.create!(
  customer_uuid: "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  invoices: [invoice],
)
ChartMogul.Invoice.create(config, "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7", {
  invoices: [
    {
      external_id: "inv_1d8f4e61",
      date: "2026-02-10",
      currency: "USD",
      customer_external_id: "cus_7f9e2a41",
      data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
      line_items: [
        {
          type: "subscription",
          subscription_external_id: "sub_8c3f1b92",
          plan_uuid: "pl_aab05d54-75b4-431b-adb2-eb6b9e543207",
          service_period_start: "2026-02-10",
          service_period_end: "2026-03-10",
          amount_in_cents: 5000,
          quantity: 1,
        },
      ],
    },
  ],
});
$line_item = new ChartMogul\LineItems\Subscription([
  "subscription_external_id" => "sub_8c3f1b92",
  "plan_uuid" => "pl_aab05d54-75b4-431b-adb2-eb6b9e543207",
  "service_period_start" => "2026-02-10",
  "service_period_end" => "2026-03-10",
  "amount_in_cents" => 5000,
  "quantity" => 1
]);

$invoice = new ChartMogul\Invoice([
  "external_id" => "inv_1d8f4e61",
  "date" => "2026-02-10",
  "currency" => "USD",
  "customer_external_id" => "cus_7f9e2a41",
  "data_source_uuid" => "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  "line_items" => [$line_item]
]);

ChartMogul\CustomerInvoices::create([
  "customer_uuid" => "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  "invoices" => [$invoice]
]);
lineItem := &cm.LineItem{
  Type:                   "subscription",
  SubscriptionExternalID: "sub_8c3f1b92",
  PlanUUID:               "pl_aab05d54-75b4-431b-adb2-eb6b9e543207",
  ServicePeriodStart:     "2026-02-10",
  ServicePeriodEnd:       "2026-03-10",
  AmountInCents:          5000,
  Quantity:               1,
}

invoice := &cm.Invoice{
  ExternalID:         "inv_1d8f4e61",
  Date:               "2026-02-10",
  Currency:           "USD",
  CustomerExternalID: "cus_7f9e2a41",
  DataSourceUUID:     "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  LineItems:          []*cm.LineItem{lineItem},
}

api.CreateInvoices(
  []*cm.Invoice{invoice},
  "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
)
chartmogul.Invoice.create(
  config,
  uuid="cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  data={
    "invoices": [
      {
        "external_id": "inv_1d8f4e61",
        "date": datetime(2026, 2, 10),
        "currency": "USD",
        "customer_external_id": "cus_7f9e2a41",
        "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
        "line_items": [
          {
            "type": "subscription",
            "subscription_external_id": "sub_8c3f1b92",
            "plan_uuid": "pl_aab05d54-75b4-431b-adb2-eb6b9e543207",
            "service_period_start": datetime(2026, 2, 10),
            "service_period_end": datetime(2026, 3, 10),
            "amount_in_cents": 5000,
            "quantity": 1,
          }
        ],
      }
    ]
  },
)

Downgrading to a free plan

When the customer downgrades to a free plan, use the Import Invoices endpoint to create a new zero-value invoice:

curl -X POST "https://api.chartmogul.com/v1/import/customers/cus_f466e33d-ff2b-4a11-8f85-417eb02157a7/invoices" \
     -u YOUR_API_KEY: \
     -H "Content-Type: application/json" \
     -d '{
            "invoices": [
              {
                "external_id": "inv_6a2c8b37",
                "date": "2026-03-10",
                "currency": "USD",
                "customer_external_id": "cus_7f9e2a41",
                "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
                "line_items": [
                  {
                    "type": "subscription",
                    "subscription_external_id": "sub_8c3f1b92",
                    "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
                    "service_period_start": "2026-03-10",
                    "amount_in_cents": 0,
                    "quantity": 1
                  }
                ]
              }
            ]
        }'
line_item = ChartMogul::LineItems::Subscription.new(
  subscription_external_id: "sub_8c3f1b92",
  plan_uuid: "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
  service_period_start: Time.utc(2026, 3, 10),
  amount_in_cents: 0,
  quantity: 1,
)

invoice = ChartMogul::Invoice.new(
  external_id: "inv_6a2c8b37",
  date: Time.utc(2026, 3, 10),
  currency: "USD",
  customer_external_id: "cus_7f9e2a41",
  data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  line_items: [line_item],
)

ChartMogul::CustomerInvoices.create!(
  customer_uuid: "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  invoices: [invoice],
)
ChartMogul.Invoice.create(config, "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7", {
  invoices: [
    {
      external_id: "inv_6a2c8b37",
      date: "2026-03-10",
      currency: "USD",
      customer_external_id: "cus_7f9e2a41",
      data_source_uuid: "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
      line_items: [
        {
          type: "subscription",
          subscription_external_id: "sub_8c3f1b92",
          plan_uuid: "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
          service_period_start: "2026-03-10",
          amount_in_cents: 0,
          quantity: 1,
        },
      ],
    },
  ],
});
$line_item = new ChartMogul\LineItems\Subscription([
  "subscription_external_id" => "sub_8c3f1b92",
  "plan_uuid" => "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
  "service_period_start" => "2026-03-10",
  "amount_in_cents" => 0,
  "quantity" => 1
]);

$invoice = new ChartMogul\Invoice([
  "external_id" => "inv_6a2c8b37",
  "date" => "2026-03-10",
  "currency" => "USD",
  "customer_external_id" => "cus_7f9e2a41",
  "data_source_uuid" => "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  "line_items" => [$line_item]
]);

ChartMogul\CustomerInvoices::create([
  "customer_uuid" => "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  "invoices" => [$invoice]
]);
lineItem := &cm.LineItem{
  Type:                   "subscription",
  SubscriptionExternalID: "sub_8c3f1b92",
  PlanUUID:               "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
  ServicePeriodStart:     "2026-03-10",
  AmountInCents:          0,
  Quantity:               1,
}

invoice := &cm.Invoice{
  ExternalID:         "inv_6a2c8b37",
  Date:               "2026-03-10",
  Currency:           "USD",
  CustomerExternalID: "cus_7f9e2a41",
  DataSourceUUID:     "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
  LineItems:          []*cm.LineItem{lineItem},
}

api.CreateInvoices(
  []*cm.Invoice{invoice},
  "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
)
chartmogul.Invoice.create(
  config,
  uuid="cus_f466e33d-ff2b-4a11-8f85-417eb02157a7",
  data={
    "invoices": [
      {
        "external_id": "inv_6a2c8b37",
        "date": datetime(2026, 3, 10),
        "currency": "USD",
        "customer_external_id": "cus_7f9e2a41",
        "data_source_uuid": "ds_fef05d54-47b4-431b-aed2-eb6b9e545430",
        "line_items": [
          {
            "type": "subscription",
            "subscription_external_id": "sub_8c3f1b92",
            "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206",
            "service_period_start": datetime(2026, 3, 10),
            "amount_in_cents": 0,
            "quantity": 1,
          }
        ],
      }
    ]
  },
)

Where the data appears

Once imported, free subscriptions appear in: