How-to guide for charging-as-a-service

Build a charging emulator demo app using Totogi APIs

Totogi is a multi-tenant, serverless monetization platform for communications service providers, also known as telcos or CSPs. CSPs can use Totogi Charging-as-a-Service to collect billing data and usage information from their subscribers using their core networks.

Follow our step-by-step guide for building a basic mobile phone emulator demo app that generates 5G 3GPP charging requests to Totogi Charging-as-a-Service, using APIs to incorporate the charger into existing BSS applications, including:

Totogi Account Management GraphQL APIs that interact with subscriber accounts and devices

5G HTTP Charging APIs that create account charges

Totogi Notifications documentation for creating real-time account balance notifications

– a Totogi Plan Design GUI that creates plans.

Let’s take a look at how we built the frontend and backend of our charging emulator demo app, and how it integrates with Totogi Charging-as-a-Service:

To build this demo app, we’ll be abstracting away the components of the typical telco/CSP infrastructure, such as actual subscribers and user equipment, the core network components eNodeBs, packet gateways, IP multimedia systems, and few dozen other components not pictured below, depending on the implementation and generation of the CSP core network.

In this example, we are simulating the charging messages that would be generated by the 4G Packet Gateway and 5G Service Management Function. Also, in lieu of operating a core network and order management system, we’ll be creating a frontend application that interacts directly with Totogi Account Management APIs to configure the correct Totogi demo account, create, manage demo accounts and devices, and mock the usage of services like SMS, voice, and data:

While the frontend can use most Totogi APIs (all of the GraphQL APIs that are designed to be consumed from web interfaces), we do need one backend component to proxy the mocked charging requests.

This is because Totogi Charging-as-a-Service is designed to be used as a machine-to-machine API, and to receive information from the local CSP infrastructure like a packet gateway. In fact, the charger actually supports multiple methods of receiving network traffic: both a 4G Diameter interface and a 5G N40 API. In this example, we’ll be using the 5G REST HTTP/2 N40 API.

Build the frontend of the charging emulator demo app

The Totogi charging emulator demo app will have a frontend that emulates a subscriber using their mobile phone. The emulator makes it simple to simulate different types of usage and to visualize the impact on balances and notifications. This demo app accesses several of the Totogi Account Management APIs to do things like load plan and plan version details, determine initial balances, and create and manage new devices in the system that we want to demo with.

Most of this happens behind the scenes and leaves us with a very simple UI that allows us to simulate the most basic components of a subscriber plan:

Here we show an example of a demo device view:

In this example, we see the current balances for that device at the top. These are updated regularly by polling one of the Totogi Account Management APIs.

On the left side, we have a mocked phone that can simulate these different charging interactions by sending requests to a backend proxy that sends them to the Totogi 5G Charging APIs.

On the right side, we have a running log of all the charging interactions to compare against as well as low-balance notifications from Totogi Notifications. These are automatic notifications that CSPs may subscribe to in order to process events like low-balance notifications, plan expiration, and new subscriptions. The power of this sort of subscription enables automated top-up reminders to lifecycle management processing.

Let’s take a look at this in more detail:

Access to Totogi APIs is limited to authorized OAuth 2.0 tokens to use them. The frontend starts by making a request to the Totogi OAuth endpoint to retrieve tokens to authenticate and authorize the account.

Next, it makes a series of requests to Totogi Account Management APIs to find the most recently published plan, then creates a subscriber account and demo device associated with the latest plan.

After this, it uses the UI shown earlier to send various requests for SMS, voice, and data charging requests to a custom backend API. In a standard implementation, this step would go directly to the Totogi charger from the packet gateway (PGW). Since Totogi Charging-as-a-Service is not designed to be called from web applications (it does not enable CORS), our browser-based application needs to send a request to a proxy API that can emulate a PGW.

That proxy API takes a few parameters from the frontend request including:

After making the request, the frontend continues to monitor the Totogi Account Management APIs to review the balances for the demo device and update the page accordingly. The frontend of the demo app also polls the backend for recently received low-balance notifications and displays them in the right-hand log window.

Build the backend of the charging emulator demo app

Now, let’s see how we built the backend application for the Totogi charging emulator demo app, and how it interacts with the Totogi Account Management APIs as seen in the above sequence diagram. Our backend application handles several different needs:

  1. processing and storing notifications from Totogi
  2. providing an API to get saved notifications for different devices
  3. proxying 5G charging requests for the frontend

To handle these needs, our application acts as a serverless framework application in AWS that creates AWS resources, such as AWS Lambda functions, API Gateway endpoints, an AWS DynamoDB table, and an integration with an Amazon EventBridge bus that receives Totogi Notifications for processing. This application is in the backend folder of our demo code. Here’s how it works:


With any Serverless Framework application, the core configuration is inside the serverless.yml file. For us, this starts with configuring a few basics including a service name, framework version, AWS region, and the runtime language and version to use.

We also specify an environment variable for the DynamoDB table name that will be notifications-dev or notifications-prod depending on the stage we’re deploying to.

After that, we configure Cross-Origin Resource Sharing for our HTTP API so that we can use it from our browser app. We also set up the Identity and Access Management permissions our service should have access to. In this case, only Query and PutItem operations on our DynamoDB table.

After all of this we specify the different Lambda Functions and the events that will be triggering them:

This includes the proxyCharging API endpoint to create 5G charging requests and the getNotifications endpoint so that our application can fetch any notifications that were sent in from Totogi and then stored by our processNotifications function.

The processNotifications function is configured to process all the events going into our EventBridge that are arriving from the 266643203619 account (where Totogi sends in events from). The process of creating an Amazon EventBridge and configuring it to work with Totogi is outside of the scope of this post, but it’s a very quick process for any of our customers.

The last portion of the configuration references a file where we describe our DynamoDB infrastructure along with details to help manage Python dependencies and service packaging:


The DynamoDB table used by the application to store notifications data has a partition key (pk) and sort key (sk). We are using the single table design pattern, and our keys are prefixed with the object type stored in each row.

With all this infrastructure configured we can look at some of the application code.

Processing Totogi Notifications

When processing notifications our EventBridge Bus has a Rule configured that sends event payloads to Lambda. Here’s what an example event looks like notifying us that the voice balance for a subscriber account was normal but is now low:

What constitutes a “low” balance? That’s completely configurable in our Plan Design UI. Right now, it means dropping below 50% of the allocated balance. We have notifications for any kind of low balance: voice, text, and data. We also have even more notifications CSP software teams can use such as when a subscriber is created or activated.

Process these events to send out low-balance warnings to subscribers, handle lifecycle workflows, manage marketing campaigns, and much more!
In our application however, all we’re doing is storing notifications for low balances that can easily be queried for in DynamoDB based on the device we’re working with. This is as simple as importing a few dependencies and configuring our DynamoDB table resource:

… and then checking if the event is a threshold event and handling it accordingly:

To check if the event is a newly breached threshold, we look for a current state of low (because Totogi also provides notifications when a threshold goes from low back to normal) and that the counter contains the text AllowanceThreshold:

To handle the threshold, we determine which kind of threshold it is:

… and save the data to DynamoDB:

Getting Totogi Notifications

Getting back the relevant notifications for our accounts after we’ve stored them in our backend is even simpler.

We set up some dependencies and our DynamoDB Table resource:

… then we run a query on the table using the query string parameters from the incoming GET request event:

This returns all the relevant notifications we’re looking for and we can display them within the frontend.

The 5G Charging Proxy

The final purpose for our backend application is to proxy requests from the frontend and turn them into 5G charging API requests. This is done on the backend for two reasons:

  1. 5G requests cannot be made directly from a browser due to CORS restrictions on the 5G API
  2. 5G API requires HTTP2 and most frontend clients do not currently do not support this without additional configuration (Axios, fetch etc.)

This entire process would usually be handled by a local on-premises application, most likely as a component of the PGW. But because we’re mimicking the network traffic we need our own application to handle this for us.

Our frontend UI offers a few structured options for charging requests: voice, SMS, and data consumption. But the backend translates this simple request into a full 5G charging message. Normally in the process of an ongoing phone conversation in a 5G context we would have a series of charging requests like this:

But for this demo, we’ll do these all at once and in sequence in order to charge precisely what the demo app would like us to.

If we want to charge 5 minutes of voice we send an init request reserving 5 minutes, then send an update request using 5 minutes and reserving no additional time, and a final terminate request ending the session and neither reserving or using any time. At this point the account balance would be updated.

Here’s what this looks like in practice. We create the data for the initupdate, and terminate requests in a very similar way by including the  providerIddeviceIdvolume and ratingGroupNumber  (corresponding to voice, text, or data in this case). We also have a unitTypeIdentifier utility function to pick the type of unit we might need when charging voice minutes (time), SMS or money (serviceSpecificUnits), data (totalVolume), or other custom rating groups. And we have some faked locationReportingChargingInformation information and an auto-generated timestamp:

The update_data request data has an incremented sequence number, and records the units used:

… and the terminate_data request data simply closes things out without using or requesting any additional volume for the request:

The request data in these requests is sent into the Charging API via the Python HTTP client, httpx. The httpx client is HTTP2-compatible and makes sending these requests significantly easier than other common libraries like requests for Python or Axios for Node.js. Here’s an example with the init request.

First, we import the required libraries and utility functions:

The *_data functions are shown above. The headers contain required token information to secure the request, and the *_url functions help us create the 3GPP 5G NCHF URLs we need to send requests to: this is because the URL for update and terminate requests must contain the session ID information from the init request.

Then, we create the httpx client and functions to handle the three HTTP requests:

With all of this set up, we chain it all together when the request comes in:

When this process completes, the charges will be recorded in our account and the balances will be updated when our frontend queries for the account balances. Also, depending on those balances, this request might trigger a low balance notification.


Demo in action

And that’s the core of this project! Let’s take a look at a full demo with this tool. We’ll start by using Totogi Plan Design GUI, then use this charging emulator demo app to try out our new plan! Take a look at our 3-minute explaier video for an overview:

Building our own network

This is a great start at understanding how to build a charging emulator demo app you can build with Totogi APIs, but we aren’t done yet.

Right now, we’re also working on creating an even more end-to-end demo experience. To do this, we are building our own mobile core network based on Magma and the Citizens Broadband Radio Service in the United States.

Essentially, this means that we will be running our own communications service provider within a few meters of a radio antenna in one of our backyards. We will have a lab phone that uses the CBRS band to communicate with a local eNodeB which is tied over the internet backhaul to our Magma Core 5G network. That network is configured to send usage data to Totogi Charging-as-a-Service for that device. And because our charger integrates directly with our plan designers, we’ll be able to alert and act on that charging data.

Get started today

Everything we’ve shown in this post and demo video is just the most basic functionality that our charger supports. We’re getting ready to showcase all the other amazing features of our charging engine. Watch how easy it is to tackle things like:

… and quite a bit more.

Congratulations, you should now have your very own basic mobile phone emulator demo app that generates 5G 3GPP charging requests to Totogi Charging-as-a-Service, using APIs to incorporate the charger into existing BSS applications. We hope you check out more of our how-to guides to learn more about the capabilities of the Totogi monetization platform, or book a demo with us today.

charging-as-a-service on aws

Try out Totogi on AWS for yourself

AWS - Amazon Web Services