Meter and bill active users with Metering & Billing generic meters

TL;DR

To meter active users in Konnect, create a generic meter with UNIQUE_COUNT aggregation to track unique users per billing period. Then define a feature and plan to invoice customers based on their seat count. Create a customer that includes usage from subject and assign the customer to your plan. Finally, send an event that includes the subject that is associated with the customer to generate an invoice.

Prerequisites

If you don’t have a Konnect account, you can get started quickly with our onboarding wizard.

  1. The following Konnect items are required to complete this tutorial:
    • Personal access token (PAT): Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.
  2. Set the personal access token as an environment variable:

    export KONNECT_TOKEN='YOUR KONNECT TOKEN'
    

You need the Metering & Billing Admin role in Konnect to configure Metering & Billing.

Generic metering is a flexible way to meter events from a variety of sources. This guide shows you how to use generic metering in Metering & Billing by demonstrating how to track and invoice customers based on the number of unique active users (seats) per month.

Per-seat billing is a common pricing model for SaaS products where customers are charged based on how many distinct users access the platform in a billing period. By using the UNIQUE_COUNT aggregation, you can count unique users accurately even if the same user triggers multiple events.

In this guide, you’ll:

  • Create a generic meter that counts unique active users
  • Create a feature to make that usage billable
  • Create a per-seat plan with usage-based pricing
  • Start a subscription for a customer
  • Send usage events and validate the invoice

Create a meter

In Metering & Billing, meters track and record the consumption of a resource or service over time. For per-seat billing, you’ll create a generic meter using the UNIQUE_COUNT aggregation. This counts the number of distinct user_id values seen within the billing period, so if the same user is active multiple times, they’re only counted once.

  1. In the Konnect sidebar, click Metering & Billing.
  2. Click New meter.
  3. In the Name field, enter Active users total.
  4. In the Description field, enter Active Users.
  5. In the Event Type Filter field, enter user_activity.
  6. From the Aggregation dropdown menu, select “UNIQUE COUNT”.
  7. In the Value property field, enter $.user_id.
  8. Click Save.

Create a feature

Meters collect raw usage data, but features make that data billable. Without a feature, usage is tracked but not invoiced. Now that you’re metering active users, you need to associate that meter with a named, customer-facing feature.

  1. In the Konnect sidebar, click Metering & Billing.
  2. In the Metering & Billing sidebar, click Product Catalog.
  3. Click Create Feature.
  4. In the Name field, enter active-users.
  5. From the Meter dropdown menu, select “Active users total”.
  6. Click Save.

Create a plan and rate card

Plans are the core building blocks of your product catalog. They are a collection of rate cards that define the price and access of a feature. Plans can be assigned to customers by starting a subscription.

A rate card describes the price and usage limits or access control for a feature. Rate cards are made up of the associated feature, price, and optional entitlements.

In this section, you’ll create a Per-Seat plan that charges customers $1 per active user per month:

  1. In the Konnect sidebar, click Metering & Billing.
  2. In the Metering & Billing sidebar, click Product Catalog.
  3. Click the Plans tab.
  4. Click Create Plan.
  5. In the Name field, enter Per-Seat.
  6. From the Billing cadence dropdown menu, select 1 month.
  7. Click Save.
  8. Click Add Rate Card.
  9. From the Feature dropdown menu, select “active-users”.
  10. Click Next Step.
  11. From the Pricing model dropdown menu, select Usage based.
  12. In the Price per unit field, enter 1.

    We’re using $1 here to make it easy to see invoice amount changes in the customer invoice. Change this price in a production instance to match your own pricing model.

  13. Click Next Step.
  14. Select Boolean.
  15. Click Save Rate Card.
  16. Click Publish Plan.
  17. Click Publish.

Start a subscription

Customers are the entities that pay for consumption. Here you’ll create a customer and subscribe them to the Per-Seat plan.

  1. In the Konnect sidebar, click Metering & Billing.
  2. In the Metering & Billing sidebar, click Billing.
  3. Click Create Customer.
  4. In the Name field, enter Acme Inc.
  5. In the Key field, enter acme-inc.

    This value links incoming usage events to this customer. Events with "subject": "acme-inc" will be attributed to Acme Inc.

  6. Click Save.
  7. Click the Subscription tab.
  8. Click Create a Subscription.
  9. From the Subscribed Plan dropdown, select Per-Seat.
  10. Click Next Step.
  11. Click Start Subscription.

Validate

Send usage events to Metering & Billing using the CloudEvents format. Each event represents a user interaction in your application. The meter counts each unique user_id value once per billing period. To validate, we’ll send events for three distinct users: alice, bob, and carol.

Important: When you send events, they must have a unique id. Metering & Billing deduplicates events with the same id.

  1. Export the current time:
    export EVENT_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
    

    Metering & Billing only invoices and meters events that are sent after the subscription is created.

  2. Send an event for alice:

    curl -X POST "https://us.api.konghq.com/v3/openmeter/events" \
         --no-progress-meter --fail-with-body  \
         -H "Authorization: Bearer $KONNECT_TOKEN"\
         -H "Content-Type: application/cloudevents+json" \
         --json '{
           "specversion": "1.0",
           "type": "user_activity",
           "id": "57B5F342-B8D5-49AE-9D6C-350C1D92155C",
           "source": "acme-platform",
           "time": "'$EVENT_TIME'",
           "datacontenttype": "application/json",
           "subject": "acme-inc",
           "data": {
             "user_id": "alice"
           }
         }'
    
  3. Send an event for bob:

    curl -X POST "https://us.api.konghq.com/v3/openmeter/events" \
         --no-progress-meter --fail-with-body  \
         -H "Authorization: Bearer $KONNECT_TOKEN"\
         -H "Content-Type: application/cloudevents+json" \
         --json '{
           "specversion": "1.0",
           "type": "user_activity",
           "id": "F388B902-7A82-4C40-BC89-448CFA5DDC1B",
           "source": "acme-platform",
           "time": "'$EVENT_TIME'",
           "datacontenttype": "application/json",
           "subject": "acme-inc",
           "data": {
             "user_id": "bob"
           }
         }'
    
  4. Send an event for carol:

    curl -X POST "https://us.api.konghq.com/v3/openmeter/events" \
         --no-progress-meter --fail-with-body  \
         -H "Authorization: Bearer $KONNECT_TOKEN"\
         -H "Content-Type: application/cloudevents+json" \
         --json '{
           "specversion": "1.0",
           "type": "user_activity",
           "id": "46C16EE0-6174-4336-A539-AEC3AD1E0485",
           "source": "acme-platform",
           "time": "'$EVENT_TIME'",
           "datacontenttype": "application/json",
           "subject": "acme-inc",
           "data": {
             "user_id": "carol"
           }
         }'
    
  5. Now, send a second event for alice to confirm that UNIQUE_COUNT doesn’t duplicate repeated users:

    curl -X POST "https://us.api.konghq.com/v3/openmeter/events" \
         --no-progress-meter --fail-with-body  \
         -H "Authorization: Bearer $KONNECT_TOKEN"\
         -H "Content-Type: application/cloudevents+json" \
         --json '{
           "specversion": "1.0",
           "type": "user_activity",
           "id": "2843D4B1-C8F8-408E-9F28-6D4EB44E5A8B",
           "source": "acme-platform",
           "time": "'$EVENT_TIME'",
           "datacontenttype": "application/json",
           "subject": "acme-inc",
           "data": {
             "user_id": "alice"
           }
         }'
    

Even though four events were sent, the meter counted only three unique users. Now check the invoice:

  1. In the Konnect sidebar, click Metering & Billing.
  2. In the Metering & Billing sidebar, click Billing.
  3. Click Acme Inc.
  4. Click the Invoicing tab.
  5. Click Preview Invoice.

You’ll see active-users listed in Lines with a quantity of 3, reflecting three unique active users.

In this guide, you’re using the sandbox for invoices. To deploy your subscription in production, configure a payments integration in Metering & Billing > Settings, like Stripe.

Cleanup

If you created a new control plane and want to conserve your free trial credits or avoid unnecessary charges, delete the new control plane used in this tutorial.

FAQs

One reason why you might not see events in a customer’s invoice is if the event was sent before the subscription was created. Metering & Billing only invoices and meters events that are sent after the subscription is created.

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!