Skip to main content

Billing for SaaS Products

This guide walks you through setting up billing for a SaaS product with Monk. We’ll cover the complete flow from customer creation to automatic payment collection.

What We’ll Build

By the end of this guide, you’ll have:
  • Customers linked to Stripe for payment collection
  • Meters to track usage (API calls, tokens, etc.)
  • Plans that bundle pricing into reusable templates
  • Contracts that subscribe customers to plans
  • Auto-pay for automatic payment collection
  • Usage tracking via API integration
This guide assumes you have a Monk account and have connected your Stripe account. If you haven’t done this yet, visit the Dashboard to get started.

Example Scenario

Let’s say you’re building an AI agent SaaS with the following pricing model:
PlanMonthly FeeUsage Rate
Free$0$0.10 per API call
Pro$50$0.08 per API call
Customers on the Pro plan will have auto-pay enabled, so they’re charged automatically each month without any manual intervention.

Step 1: Create Your Customer

First, create a customer in Monk. If you already have a Stripe customer, you can link them directly to avoid waiting for webhook synchronization.

Via API

curl -X POST "https://api.monk.com/v1/customers" \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "paymentProviderId": "cus_xxx",
    "provider": "stripe"
  }'
The paymentProviderId and provider parameters are optional but recommended. They:
  • Link the Monk customer to an existing Stripe customer
  • Enable auto-pay using the customer’s saved payment methods
  • Prevent duplicate customer creation when Stripe webhooks arrive
Best Practice: Create the Stripe customer first, then pass the ID to Monk. This ensures immediate linkage without waiting for webhook synchronization.

Via Dashboard

  1. Navigate to Customers in your Monk dashboard
  2. Click Add Customer
  3. Enter the customer details
  4. Optionally link to an existing Stripe customer
Create Customer form showing company name, address fields, VAT numbers, and options for card payments and auto follow-up

Learn More

See the full tutorial on creating customers and contracts

Step 2: Set Up a Meter

Meters define what you’re measuring. For our AI agent, we’ll track API calls.

Via Dashboard

  1. Navigate to Products → Meters
  2. Click Create Meter
  3. Configure:
    • Code: API_CALL (the meter identifier)
    • Event Name: call_count (the event name to listen for)
    • Display Name: “API Calls”
    • Aggregation: Count (number of API calls)
Usage-Based page showing meters tab with columns for Code, Display Name, Aggregation type (COUNT, SUM), Billable Metric, and Status

Key Concepts

PropertyDescriptionExample
CodeUnique meter identifierAPI_CALL, STORAGE_GB
Event NameThe event name the meter listens forcall_count, storage_used
AggregationHow usage is combinedCount, Sum, Max, Unique Count
Meters decouple measurement from pricing. You can have different pricing per customer while using the same meter across all of them.

Learn More

See the full tutorial on creating meters

Step 3: Create Your Plans

Plans are reusable pricing templates. Create one for each tier.
Plans page showing a table of plans with name, status, number of prices, currency, version, and creation date

Free Plan

  1. Navigate to Products → Plans
  2. Click Create Plan
  3. Configure:
    • Name: “Free”
    • Net Terms: Net 30 (or your preference)
    • Currency: USD
  4. Add pricing items:
    • Usage-based price linked to API_CALL meter
    • $0.10 per API call

Pro Plan

  1. Create another plan named “Pro”
  2. Configure:
    • Net Terms: Due on receipt (Net 0) — required for auto-pay
    • Auto-pay default: Enabled
  3. Add pricing items:
    • Fixed monthly fee: $50
    • Usage-based price: $0.08 per API call
Plan detail page showing currency, net terms, invoice delivery, auto-pay settings, and a prices table with usage-based and flat subscription pricing
Auto-pay requires Net 0 (due on receipt) payment terms. This ensures invoices are charged immediately on the invoice date.

Learn More

See the full tutorial on creating plans

Step 4: Subscribe a Customer

Create a contract to subscribe a customer to a plan.

Via API

curl -X POST "https://api.monk.com/v1/contracts" \
  -H "Authorization: Bearer mk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "planId": "plan-uuid-here",
    "customerId": "customer-uuid-here",
    "startDate": "2026-03-01"
  }'

What Happens

When you create a contract:
  1. Invoices are pre-generated for each billing period
  2. Line items are created based on the plan’s pricing
  3. Auto-pay is enabled if the plan has it configured
  4. Usage events will automatically update the correct invoice

Via Dashboard

  1. Navigate to Products → Plans
  2. Click on the plan (e.g., “Pro”)
  3. Click Create Contract
  4. Select the customer and start date
Create contract modal showing customer dropdown, contract period with start and end date fields, and the plan's pricing details

Learn More

See the full tutorial on creating contracts

Step 5: Collect Payment Information

For auto-pay to work, customers need a saved payment method in Stripe.

Payment Portal

When customers pay their first invoice, they can opt into auto-pay through Monk’s payment portal:
  1. Customer receives invoice email with payment link
  2. Customer pays via Stripe Checkout
  3. Customer checks “Save payment method for future invoices”
  4. Payment method is saved and linked to the contract

Stripe SetupIntent (Custom Integration)

Collect payment information via Stripe Elements following this guide. Although Stripe’s hosted checkout flow is also an option, we recommend Stripe Elements for their ability to customize and embed the form directly into your experience:
  • The payment information you’re collecting should be usable for future, recurring charges without the customer present
  • Use SetupIntent (not PaymentIntent) since you’re saving the payment method, not charging immediately
// Server-side: Create SetupIntent
const setupIntent = await stripe.setupIntents.create({
  customer: 'cus_xxx',
  usage: 'off_session',
});

// Client-side: Confirm with Stripe Elements
const { error } = await stripe.confirmSetup({
  clientSecret: setupIntent.client_secret,
  elements,
});
Set usage: 'off_session' when creating the SetupIntent. This ensures the payment method can be charged without the customer present.
For detailed Stripe integration instructions, see:

Learn More

See the full tutorial on setting up auto-pay

Step 6: Send Usage Events

As customers use your product, send usage events to Monk.

Via API

const recordUsage = async (customerId, requestId) => {
  const response = await fetch('https://events-api.monk.com/v1/events', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.MONK_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      customer_id: customerId,
      event_name: 'call_count',
      idempotency_key: `call_count_${customerId}_${requestId}`,
    }),
  });

  if (!response.ok) {
    // Queue for retry
    console.error('Failed to record usage, queuing for retry');
  }
};

Key Fields

FieldRequiredDescription
customer_idYesThe Monk customer UUID
event_nameYesThe event name matching a meter (e.g., call_count)
idempotency_keyNoUnique key to prevent duplicates (auto-generated if omitted)
timestampNoWhen the event occurred (defaults to now)
propertiesNoAdditional metadata as key-value pairs

How Matching Works

  1. You send an event with event_name: "call_count"
  2. Monk finds meters configured with eventName: "call_count" (e.g., the API_CALL meter)
  3. Monk finds the customer’s active contract
  4. Monk finds the draft invoice for the current billing period
  5. Monk matches the line item via meter → pricing relationship
  6. Usage is aggregated and the invoice total is updated
Usage-Based Events tab showing a list of usage events with timestamp, event name, properties JSON, and customer name
Usage matching is asynchronous. Events are processed in the background, typically within a minute.

API Reference

See the full API specification for usage events

Step 7: Invoice Lifecycle

Understanding how invoices flow through the system:

Invoice Statuses

StatusDescription
DraftedInvoice created, not yet sent
In ProgressUsage being recorded
SentInvoice sent to customer
PaidPayment received
Invoice preview showing line items with descriptions, quantities, unit prices, and totals

Auto-Pay Flow

For contracts with auto-pay enabled:
  1. Invoice reaches its invoiceDate
  2. Monk’s daily scheduler finds due invoices with auto-pay
  3. Stripe PaymentIntent is created and confirmed
  4. Invoice is marked as Paid when payment succeeds
  5. Customer receives payment confirmation email
Auto-pay only works for Net 0 (due on receipt) plans. The charge happens on the invoice date, not the due date.

Next Steps

Billing for AI Products

Dimensional pricing for AI/ML (different rates by region, model, etc.)

Create your first Meter

Detailed tutorial on meters

Create your first Plan

Detailed tutorial on plans

Create your first Contract

Detailed tutorial on contracts

Set up Auto-Pay

Detailed tutorial on auto-pay