Skip to main content

Billing for AI Products

This guide walks you through setting up billing for an AI product where rates vary by attributes like region, model, or outcome. We’ll build a complete billing system for an AI call center with dimensional pricing.

What We’ll Build

By the end of this guide, you’ll have:
  • Meters with dimensions to track AI calls by region and outcome
  • Rate cards with different prices per dimension combination
  • Plans with dimensional usage pricing
  • Contracts that generate invoices with dimensional breakdowns
  • Usage tracking with dimension properties
  • Invoices showing per-dimension line items
This guide assumes familiarity with Monk basics. If you’re new to Monk, start with the SaaS Billing Guide first.

Example Scenario

You’re building an AI-powered call center platform. Your pricing varies by:
DimensionValues
RegionUS, EU, APAC
Call Outcomeresolved, transferred, escalated
Different combinations have different costs to you (regional infrastructure, escalation handling), so you charge per minute accordingly:
RegionOutcomeRate/Minute
USresolved$0.20
UStransferred$0.40
USescalated$0.60
EUresolved$0.25
EUtransferred$0.50
EUescalated$0.75
APACresolved$3.00
APACtransferred$0.60
APACescalated$0.90
$0.40 (fallback)

Step 1: Create a Dimensional Meter

First, create a meter that tracks AI calls and groups usage by dimension keys.
  1. Open your Monk dashboard
  2. Go to Usage-basedMeters
  3. Click Create Meter

Configure the Meter

FieldValue
CodeAI_CALL
Display NameAI Calls
Event Nameai_call
AggregationSum
Aggregation Keyduration_minutes
Group Keysregion, call_outcome
Create Meter dialog with Code, Display Name, Aggregation, and Group Keys fields
Group Keys are the event properties Monk uses to break down usage for dimensional pricing. They must match your event property names exactly.
Click Save to create the meter.

Step 2: Create a Rate Card

Rate cards define prices for specific dimension combinations.
  1. Go to Usage-based → Dimensional Rates
  2. Click Create dimensional rate
  3. Select AI Calls as the meter

Add Rate Entries

Add each dimension combination and its rate:
Rate Card showing table of region/outcome combinations with rates
RegionOutcomeRate/Min
USresolved$0.20
UStransferred$0.40
USescalated$0.60
EUresolved$0.25
EUtransferred$0.50
EUescalated$0.75
APACresolved$0.30
APACtransferred$0.60
APACescalated$0.90
You don’t need every combination. Unmatched events use the fallback rate from the pricing configuration.
Click Save to create the rate card.

Step 3: Create Pricing with the Rate Card

Now create a pricing configuration that uses your rate card.
  1. Go to Products and Plans
  2. Click Create Product (or edit an existing product)
  3. Add a Usage-based pricing

Configure Pricing

FieldValue
NameAI Call Pricing
MeterAI Calls
Pricing ModelPer Unit
Fallback Rate$0.40
Rate Card(your rate card)
Create Pricing dialog showing meter selection, fallback rate, and rate card attachment
The Fallback Rate is critical — it’s used when events have dimension values not in your rate card. Set it to a sensible default that covers your costs.
Click Save to create the pricing.

Step 4: Create a Plan

Bundle the pricing into a plan.
  1. Go to Products and Plans
  2. Click Create Plan

Configure the Plan

FieldValue
NameAI Call Center
CurrencyUSD
Net TermsDue on receipt
Auto-payEnabled

Add Pricing Items

  1. Click Add Pricing Item
  2. Select Usage-Based
  3. Choose AI Call Pricing
Create plan dialog showing AI Call Pricing added to the plan
Click Save to create the plan.

Step 5: Create a Contract via Contract Extraction

Monk’s contract extraction flow lets you upload a customer agreement (PDF or image) and automatically extract commercial terms. This is common for sales-led growth (SLG) motions where customers negotiate custom terms.

Upload the Contract

  1. Go to Process Contract
  2. Upload your customer’s signed agreement
  3. Monk extracts customer info, contract dates, payment terms, and pricing

Review Commercial Terms

After extraction, you’ll see the Commercial Terms page:
Commercial terms page showing contract details, prepaid credits, and plan selection
Key fields extracted or configured:
FieldExample Value
Contract periodNov 01, 2024 - Oct 31, 2026
Payment terms45 days
Pricing planAI Support Plan

Prepaid Credits for AI Usage

A common SLG pattern for AI products is offering prepaid credits that customers draw down as they use your service. This gives customers cost predictability while you maintain usage-based pricing. In the example above:
  • Initial grant amount: $10,000
  • Credit expiration date: Oct 31, 2026
Prepaid credits are applied automatically to usage-based charges. When credits run out, the customer is billed for overages at your standard rates.

Product Matching with Dimensional Pricing

The extraction flow matches products from your contract to your pricing catalog. Notice the AI Call Pricing is matched with all dimensional rates visible:
Contract review showing AI Call Pricing with all 9 dimensional rate combinations
The dimensional rates show exactly what this customer will be charged:
DimensionRate
US / resolved$0.20/min
US / transferred$0.40/min
US / escalated$0.75/min
EU / resolved$0.25/min
EU / transferred$0.50/min
EU / escalated$0.75/min
APAC / resolved$0.30/min
APAC / transferred$0.60/min
APAC / escalated$0.90/min

Confirm the Contract

  1. Review all extracted terms
  2. Click Next to proceed to Step 3 (Review contract information)
  3. Verify the final summary
  4. Click Confirm to create the contract

What Happens

When the contract is confirmed:
  1. Customer is created (or matched to existing)
  2. Contract is activated with the extracted terms
  3. Prepaid credits are granted ($10,000 in this example)
  4. Invoices are pre-generated for each billing period
  5. Dimensional line items are ready to receive usage events

Step 6: Send Usage Events with Dimensions

Now integrate your application to send usage events with dimension properties.

Event Structure

Each event includes the dimension properties that determine which rate applies:
const recordAICall = async ({
  customerId,
  callId,
  region,
  outcome,
  durationMinutes,
}) => {
  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: 'ai_call',
      idempotency_key: `ai_call_${callId}`,
      properties: {
        region: region, // 'US', 'EU', or 'APAC'
        call_outcome: outcome, // 'resolved', 'transferred', or 'escalated'
        duration_minutes: durationMinutes, // Aggregation key - summed for billing
        agent_id: 'agent_456', // Additional metadata (not used for pricing)
      },
    }),
  });

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

Send Test Events

Let’s simulate a day of calls for Acme Support Co:
// Morning: US team handles calls
await recordAICall({
  customerId: 'cust_xxx',
  callId: 'call_001',
  region: 'US',
  outcome: 'resolved',
  durationMinutes: 5,
});
await recordAICall({
  customerId: 'cust_xxx',
  callId: 'call_002',
  region: 'US',
  outcome: 'resolved',
  durationMinutes: 8,
});
await recordAICall({
  customerId: 'cust_xxx',
  callId: 'call_003',
  region: 'US',
  outcome: 'transferred',
  durationMinutes: 12,
});

// Afternoon: EU team takes over
await recordAICall({
  customerId: 'cust_xxx',
  callId: 'call_004',
  region: 'EU',
  outcome: 'resolved',
  durationMinutes: 6,
});
await recordAICall({
  customerId: 'cust_xxx',
  callId: 'call_005',
  region: 'EU',
  outcome: 'escalated',
  durationMinutes: 15,
});

// Evening: APAC team handles overflow
await recordAICall({
  customerId: 'cust_xxx',
  callId: 'call_006',
  region: 'APAC',
  outcome: 'resolved',
  durationMinutes: 4,
});

Batch Events (High Volume)

For high-volume scenarios, batch events:
await fetch('https://events-api.monk.com/v1/events/batch', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.MONK_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    events: [
      {
        customer_id: 'cust_xxx',
        event_name: 'ai_call',
        properties: {
          region: 'US',
          call_outcome: 'resolved',
          duration_minutes: 5,
        },
      },
      {
        customer_id: 'cust_xxx',
        event_name: 'ai_call',
        properties: {
          region: 'US',
          call_outcome: 'resolved',
          duration_minutes: 8,
        },
      },
      {
        customer_id: 'cust_xxx',
        event_name: 'ai_call',
        properties: {
          region: 'EU',
          call_outcome: 'escalated',
          duration_minutes: 15,
        },
      },
      // ... more events
    ],
  }),
});
Events are processed asynchronously. Usage typically appears on invoices within a minute.
You can verify events are being received in Usage-based → Events:
Events list showing AI call events with region, call_outcome, and duration_minutes properties

Step 7: View the Dimensional Breakdown

After sending events, check the invoice to see the dimensional breakdown.
  1. Go to Customers → Acme Support Co
  2. Click on the current billing period invoice

Invoice Line Items

Each dimension combination appears as a separate line item:
Invoice showing separate line items for US/Resolved, US/Transferred, EU/Resolved, EU/Escalated, APAC/Resolved
Line ItemMinutesRate/MinAmount
AI Calls - US / Resolved13$0.20$2.60
AI Calls - US / Transferred12$0.40$4.80
AI Calls - EU / Resolved6$0.25$1.50
AI Calls - EU / Escalated15$0.75$11.25
AI Calls - APAC / Resolved4$0.30$1.20
Total50$21.35
This breakdown gives customers clear visibility into exactly what they’re being charged for — no surprises, no “black box” billing.

Viewing Events for a Dimension

Click on the quantity for any line item to view the underlying usage events filtered by that dimension:
Invoice line item showing clickable quantity with meter icon linking to usage events
This opens the Events tab with a pre-filled query that filters to the specific customer, time period, and dimension values:
Usage events page showing filtered events for a specific dimension combination

Invoice Total with Prepaid Credits

Notice the invoice shows $0.00 — this is because the usage charges are automatically deducted from the customer’s prepaid credit wallet. The “Prepaid Credits Applied” line item shows the credit deduction, and the remaining wallet balance is visible in the invoice details. Click View Email or PDF Preview to see the full invoice with dimensional breakdown that customers will receive:
Invoice PDF preview showing dimensional line items with prepaid credits applied
To monitor credit depletion in real-time, go to Customers → [Customer] → Credits and click on the wallet to see the transaction history. Each usage calculation shows the cumulative deduction per dimension:
Credit wallet transaction history showing usage deductions and remaining balance

Fallback Strategy

When an event’s dimension values don’t match any rate card entry, Monk uses the fallback rate. You can see all your dimensional rates including the fallback in Usage-based → Dimensional Rates:
Dimensional Rates list showing all rate entries including fallback catch-all rate
To create or edit the fallback rate, leave the dimension fields empty — this creates a “catch-all” entry:
Create Dimensional Rates dialog showing empty dimension fields for fallback rate
Set your fallback rate strategically:
StrategyFallback RateWhen to Use
ConservativeHighest rateNew dimensions should be profitable
Break-evenAverage rateCover costs on unknown combinations
Customer-firstLowest rateFavor customers, fix rate card quickly
Coming soon: Editing rates in the UI will be available shortly, allowing you to tweak existing rates or add new dimension combinations. Versioning is supported through the Effective From and Effective To dates — Monk tracks rate history and aggregates usage against the correct rate version based on when events occurred.

Troubleshooting

All Events at Fallback Rate

Problem: Events aren’t matching rate card entries. Check:
  1. Property names match exactly (case-sensitive)
  2. Property values match exactly (US not us)
  3. Rate card is attached to the pricing
// ❌ Wrong — property names don't match
{ region: 'US', callOutcome: 'resolved' }

// ✅ Correct — exact match to rate card
{ region: 'US', call_outcome: 'resolved' }

Missing Dimension Properties

Problem: Some events missing dimension properties. Solution: Validate before sending:
const recordAICall = async ({ customerId, callId, region, outcome }) => {
  // Validate required dimensions
  if (!region || !outcome) {
    console.error('Missing required dimension properties');
    return;
  }

  // ... send event
};

Unexpected Dimension Values

Problem: New region or outcome not in rate card. Solution: Events use the fallback rate until you update the rate card. Monitor for unexpected values and update accordingly.

Summary

You’ve built a complete AI billing system with:
  1. ✅ Dimensional meter tracking calls by region and outcome
  2. ✅ Rate card with specific prices per combination
  3. ✅ Pricing with fallback for unknown combinations
  4. ✅ Plan bundling the dimensional pricing
  5. ✅ Contract generating invoices with dimensional breakdowns
  6. ✅ Usage events with dimension properties
  7. ✅ Invoices showing transparent per-dimension charges
Customers see exactly what they’re paying for, and you can price based on your actual cost structure.

Next Steps

Dimensional Pricing Concepts

Deep dive into dimensional pricing design

Events API

Full API reference for usage events

Set Up Auto-Pay

Automatic payment collection

Testing Your Integration

Validate your billing setup