sbt-aws-moesif
TypeScript icon, indicating that this package has built-in type declarations

0.1.1 • Public • Published

Moesif API Monetization for AWS SBT

This module extends the AWS SaaS Builder Toolkit (SBT) to support usage-based billing through Moesif.

SaaS Builder Toolkit for AWS (SBT) is an open-source developer toolkit to implement SaaS best practices. SBT attempts to codify several control plane and application plane concepts such as tenant and user management, billing, and onboarding into reusable components, promoting reuse and reducing boilerplate code.

Moesif API Monetization provides a cloud-based solution for usage-based billing such as billing on API transactions, compute resources, or unique users. Then, you can invoice and collect payments automatically through popular payment providers like Stripe, Zuora, or custom invoicing solutions.

How it works

Event Ingestion

The project deploys an Amazon Data Firehose to ingest your raw usage events. Events can be API Calls such as from an Amazon API Gateway instance or custom actions triggered within your application. The firehose will send all events to Moesif's Collection API for metering and analytics.

moesif-firehose-diagram.png

For more info on how the MoesifFirehoseConstruct works, view Moesif docs on ingesting actions via Firehose

User and Tenant Management

The project also deploys a Lambda Function for user and tenant management. The lambda will listen to events like provisionSuccess to create companies and subscriptions in Moesif and your payment provider. Similarly, when receiving a deprovisionSuccess event, all subscriptions will be canceled for the tenant. You can inspect the code here.

SBT Entity Moesif Entity Description Parent
Tenant Company Your customer that you provisioned resources for. None
Tenant Subscription A single subscription for a company/tenant. Company
User User End users of your customer who login to your SaaS. Company

How to use

Prerequisites

  1. If you don't already have a SBT project deployed, follow AWS SBT's tutorial to deploy the sample hello-cdk project with a ControlPlane and CoreApplicationPlane.
  2. You already have a Moesif account. You can sign up for a trial on moesif.com

1. Install the NPM package

Within your SBT project directory, install sbt-aws-moesif via the following command:

npm install --save sbt-aws-moesif

2. Add MoesifBilling to your ControlPlane

Instantiate the MoesifBilling construct like below. You will need to set some properties to authenticate with Moesif.

export class ControlPlaneStack extends Stack {
  public readonly regApiGatewayUrl: string;
  public readonly eventBusArn: string;

  constructor(scope: Construct, id: string, props: any) {
    super(scope, id, props);
    const cognitoAuth = new CognitoAuth(this, 'CognitoAuth', {
      idpName: 'COGNITO',
      systemAdminRoleName: 'SystemAdmin',
      systemAdminEmail: '<<Your Admin Email>>',
    });

    const moesifBilling = new MoesifBilling(stack, 'MoesifBilling', {
      moesifApplicationId: '<<Your Moesif Application Id>>',
      moesifManagementAPIKey: '<<Your Moesif Management API Key>>',
      billingProviderSlug: BillingProviderSlug.STRIPE,
      billingProviderSecretKey: '<<Your Billing Provider\'s Secret Such as for Stripe>>'
    }
   );

    const controlPlane = new ControlPlane(this, 'ControlPlane', {
      auth: cognitoAuth,
      billing: moesifBilling,
    });
    this.eventBusArn = controlPlane.eventBusArn;
    this.regApiGatewayUrl = controlPlane.controlPlaneAPIGatewayUrl;
  }
}

Moesif Billing Properties

Property Name Type Required Description Default
moesifApplicationId string Required Collector Application Id from your Moesif account for event ingestion
moesifManagementAPIKey string Required Management API Key from your Moesif account. The key must have the following scopes: create:companies create:subscriptions create:users delete:companies delete:subscriptions delete:users
moesifManagementAPIBaseUrl string Override the base URL for the Moesif Mangaement API. For most setups, you don't need to set this. https://api.moesif.com
moesifCollectorAPIBaseUrl string Override the base URL for the Moesif Collector API. For most setups, you don't need to set this. https://api.moesif.net
billingProviderSlug BillingProviderSlug Required Slug for Billing Provider / Payment Gateway
billingProviderSecretKey string Required Secret Key for Billing Provider / Payment Gateway selected by billingProviderSlug
billingProviderClientId string Only if Zuora Client Id for Billing Provider / Payment Gateway. Only used when billingProviderSlug is Zuora
billingProviderBaseUrl string Only if Chargebee or Zuora Base URL for Billing Provider / Payment Gateway. Only used when billingProviderSlug is Zuora or Chargebee
tenantPlanField string Tenant object's field name that contains the plan id used when creating new subscriptions. Only used when billingProviderSlug is Zuora planId
tenantPriceField string Tenant object's field name that contains the price id used when creating new subscriptions. priceId
firehoseName string The name of the Kinesis Firehose delivery stream. By default, a unique name will be generated.
bucketName string The name of the S3 bucket for backup. By default, a unique name will be generated.
schema string Moesif Event Schema for data ingestion. By default, Moesif actions

3. Provision a Tenant

Once you deploy your updated stack, create a tenant in your AWS SBT setup using the SBT APIs.

When you create a tenant, you must also set the price id to be used for creating subscriptions, By default, the field name is priceId, but this can be overridden via the above options. If you are using Zuora, you must also set the plan id. The field email must also be set.

If your provider is set to Zuora, you must also set these fields

If you're running the hello-cdk project, this can be done by running this script to onboard a new tenant. Modify, the script to also include the price (and plan if required).

To find your plan id and price id, you can log into Moesif UI and go to Product Catalog or log into your billing provider.

DATA=$(jq --null-input \
    --arg tenantEmail "$TENANT_EMAIL" \
    --arg tenantId "$TENANT_ID" \
    '{
  "email": $tenantEmail,
  "tenantId": $tenantId,
  "priceId": "price_1MoBy5LkdIwHu7ixZhnattbh"
}')

echo "creating tenant..."
curl --request POST \
    --url "${CONTROL_PLANE_API_ENDPOINT}tenants" \
    --header "Authorization: Bearer ${ID_TOKEN}" \
    --header 'content-type: application/json' \
    --data "$DATA"

Once done, you should see the company show up in the Moesif UI. There should also be a subscription for the company in the "active" status.

The tenant will be subscribed to the price defined by defaultPriceId. This can be expanded to allow more customization.

4. Ingest Events

Now that you created a tenant, you should ingest some actions in you're newly created firehose. Actions have an action name (like "Signed Up", "API Request", or "Finished Job") which represents the usage event. You can also include arbitrary metadata with an action, which enables you to create billable metrics, usage reporting, and more. For more info, see docs on actions

You'll want to set a few fields like below:

  • action_name is a string and should include name of the event such as "Processed Payment Transaction"
  • company_id is your tenant identifier. See companies
  • transaction_id should be a random UUID for this event which Moesif uses for deduplication. Docs on Moesif idempotency.
  • request.time represents the transaction time as an ISO formatted string.
  • metadata is an object which includes any custom properties for this event. By setting metadata, you can bill on arbitrary metrics, create metrics on them, etc. For example, if the action name is "Processed Payment Transaction", you can include an amount and the currency to bill on the total amount.

For full schema and available fields, see Actions API Reference

An example action is below:

{
  "action_name": "Processed Payment Transaction",
  "request": {
    "time": "2024-03-01T04:45:42.914"
  },
  "company_id": "12345", // This is your tenant id
  "transaction_id": "a3765025-46ec-45dd-bc83-b136c8d1d257",
  "metadata": {
    "amount": 24.6,
    "currency": "USD",
    "time_seconds": 66.3
  }
}

In the above example, the action is created whenever a payment is processed. There are also two metrics we are tracking as part of the action (the amount of the payment and how long the job took). You can create billable metrics and usage reports from these attributes.

If your events are API calls, we recommend changing the MoesifEventSchema to API_CALL which provides a different schema than the above actions. See API Calls

5. Create a Billing Meter

Now that the tenant is created, follow these steps to create a billing meter in Moesif. The billing meter can filter or aggregate on any of the metadata fields you included with your action.

You should also select the provider and price defined by billingProviderSlug and defaultPriceId.

Provider Specific Requirements

Zuora

If you are using Zuora, the following fields must be set when creating a new tenant:

{
    "email": "<Customer email address>",
    "firstName": "<First name of customer contact>",
    "lastName": "<Last name of customer contact>",
    "currency": "<Three-letter ISO currency code>",
    "address": {
        "state": "<State or providence of the contact's address>",
        "country": "<The country of the contact's address>"
    }
}

Limitations

sbt-aws-moesif is in preview. Development is still ongoing. There are limitations to be aware of.

  • Deprovisioning a tenant will cancel all subscriptions but does not delete objects in case a subscription should be reactivated.

Useful commands

  • npm run build compile typescript to js
  • npm run watch watch for changes and compile
  • npm run test perform the jest unit tests

Readme

Keywords

none

Package Sidebar

Install

npm i sbt-aws-moesif

Weekly Downloads

0

Version

0.1.1

License

none

Unpacked Size

277 kB

Total Files

21

Last publish

Collaborators

  • dgilling