Skip to main content
You’ve designed the perfect usage-based pricing model in the simulator. Now it’s time to make it operational—automatically calculate bills from real usage data and send them to Stripe, your internal billing system, or wherever you need them.

Why Usage-Based Billing Matters

Traditional subscription billing doesn’t work for AI products where costs vary 10x between customers. Usage-based billing ensures you:
  • Bill for actual consumption — Charge based on spans, tokens, sessions, or any telemetry metric
  • Match revenue to costs — Your pricing scales with the value (and cost) delivered
  • Prevent surprise bills — Real-time threshold alerts when customers approach spending limits
  • Automate invoicing — Generate usage-based invoices automatically at period end
The usage-based billing system converts your telemetry data into invoices without any manual work.

How It Works

Once you activate a pricing model, the billing system automatically tracks usage and triggers events based on your configuration:
Telemetry Data              Pricing Engine              Billing Events
─────────────────    →    ──────────────────    →    ─────────────────
• Spans (with tenant_id)    1. Aggregate usage         • billing.period_end
• Sessions                  2. Apply pricing model        → Stripe webhook
• Tokens                    3. Calculate charges       • billing.threshold_reached
• Logs                      4. Trigger webhooks           → Slack alert
                           5. Update state             • billing.usage_spike
                                                          → Customer email
The system handles:
  • Period-based billing (monthly, weekly, custom)
  • Threshold monitoring (alert when customer hits $500, 1M spans, etc.)
  • Usage spike detection (notify on 2x normal usage)
  • Shadow mode reporting (test billing logic without charging customers)

Event Types

Configure webhooks to trigger on these billing lifecycle events:

billing.period_end

Fires at the end of each billing period (monthly, weekly, custom). Use this to generate invoices and sync with Stripe.

billing.threshold_reached

Real-time alert when usage crosses a defined limit (e.g., $500 spend, 1M spans). Prevents surprise bills.

billing.usage_spike

Detects abnormal usage patterns (2x+ normal usage). Helps catch runaway costs or billing anomalies.

billing.manual_export

User-triggered export for ad-hoc reporting, customer inquiries, or manual reconciliation.

Setup Guide

1. Activate Your Pricing Model

Before billing can work, ensure your pricing model is active (not in shadow mode):
// Via API
await client.pricingModels.update({
  modelId: "plan_ent_premium_001",
  status: "active"
});

// Or via dashboard
// Navigate to Pricing Models → Select Model → Click "Activate"
Shadow mode vs. Active mode: Shadow mode generates reports but doesn’t trigger billing webhooks. Use it for testing. Active mode sends real billing events.

2. Configure Webhook Endpoints

Set up webhook URLs to receive billing events: Endpoint: POST /billing/webhooks
{
  "webhook_id": "wh_stripe_prod",
  "name": "Stripe Production Webhook",
  "url": "https://api.yourcompany.com/webhooks/billing",
  "events": [
    "billing.period_end",
    "billing.threshold_reached",
    "billing.usage_spike"
  ],
  "auth": {
    "type": "hmac_sha256",
    "secret": "whsec_your_webhook_secret"
  },
  "metadata": {
    "environment": "production",
    "team": "finance"
  }
}
Response:
{
  "webhook_id": "wh_stripe_prod",
  "status": "active",
  "created_at": "2024-03-01T10:00:00Z",
  "test_url": "/billing/webhooks/wh_stripe_prod/test"
}

3. Map Customer Metadata

Every telemetry record must include customer_id for cost attribution. Decorate at ingestion time:
// When logging spans/sessions/events
await telemetry.track({
  type: "span",
  span_id: "span_abc123",
  trace_id: "trace_xyz789",
  customer_id: "cust_acme_corp",  // ← Required for billing
  usage_total_tokens: 50000,
  model: "gpt-4o"
});
Critical: Telemetry without customer_id cannot be billed. Ensure your SDK or ingestion pipeline adds this field to every event.

4. Configure Billing Triggers

Define when events should fire: Period-based billing:
{
  "trigger_type": "period_end",
  "schedule": {
    "frequency": "monthly",
    "day_of_month": 1,
    "timezone": "America/Los_Angeles"
  },
  "pricing_model_id": "plan_ent_premium_001"
}
Threshold alerts:
{
  "trigger_type": "threshold_reached",
  "threshold": {
    "metric": "total_amount",
    "value": 500.00,
    "currency": "USD"
  },
  "notification_channels": ["webhook", "email"],
  "pricing_model_id": "plan_ent_premium_001"
}
Usage spike detection:
{
  "trigger_type": "usage_spike",
  "spike_config": {
    "multiplier": 2.0,         // Alert on 2x normal usage
    "baseline_period": "7d",   // Compare to 7-day average
    "cooldown": "1h"           // Don't alert more than once per hour
  }
}

5. Test Your Webhooks

Before going live, test your webhook endpoints:
curl -X POST https://api.yourplatform.com/v1/billing/webhooks/wh_stripe_prod/test
This sends a sample billing.period_end event to verify your endpoint is configured correctly.

Webhook Payload Structure

billing.period_end

Fires at the end of each billing period with usage summary and charges:
{
  "id": "evt_billing_period_end_001",
  "type": "billing.period_end",
  "created_at": "2024-03-31T23:59:59Z",
  "data": {
    "customer_id": "cust_acme_corp",
    "period": {
      "start": "2024-03-01T00:00:00Z",
      "end": "2024-03-31T23:59:59Z"
    },
    "pricing_model": {
      "model_id": "plan_ent_premium_001",
      "version": "1.2.0",
      "name": "Enterprise Usage-Based Plan"
    },
    "summary": {
      "total_amount": 1450.00,
      "currency": "USD",
      "subtotals": {
        "rules_total": 950.00,
        "platform_fees_total": 500.00,
        "discounts_total": 0.00
      }
    },
    "breakdown": [
      {
        "rule_id": "rule_spans_001",
        "display_name": "Distributed Tracing Spans",
        "usage": {
          "raw_value": 5000000,
          "unit": "spans"
        },
        "amount": 200.00
      },
      {
        "rule_id": "rule_session_001",
        "display_name": "User Sessions",
        "usage": {
          "raw_value": 50000,
          "unit": "sessions"
        },
        "amount": 500.00
      }
    ],
    "usage_summary": {
      "sessions": 50000,
      "traces": 200000,
      "spans": 5000000,
      "raw_events": 1000000,
      "raw_bytes": 5368709120
    }
  }
}

billing.threshold_reached

Real-time alert when a customer crosses a usage or spend threshold:
{
  "id": "evt_threshold_reached_001",
  "type": "billing.threshold_reached",
  "created_at": "2024-03-15T14:23:45Z",
  "data": {
    "customer_id": "cust_acme_corp",
    "threshold": {
      "metric": "total_amount",
      "limit": 500.00,
      "current_value": 520.00,
      "currency": "USD"
    },
    "period": {
      "start": "2024-03-01T00:00:00Z",
      "current": "2024-03-15T14:23:45Z"
    },
    "pricing_model": {
      "model_id": "plan_ent_premium_001",
      "version": "1.2.0"
    },
    "usage_snapshot": {
      "sessions": 28500,
      "spans": 2850000,
      "tokens": 285000000
    }
  }
}

billing.usage_spike

Detects abnormal usage patterns:
{
  "id": "evt_usage_spike_001",
  "type": "billing.usage_spike",
  "created_at": "2024-03-15T10:00:00Z",
  "data": {
    "customer_id": "cust_acme_corp",
    "spike_detected": {
      "metric": "spans",
      "baseline_avg": 150000,
      "current_value": 350000,
      "multiplier": 2.33,
      "severity": "high"
    },
    "period": {
      "baseline": "2024-03-08T00:00:00Z to 2024-03-14T23:59:59Z",
      "spike": "2024-03-15T00:00:00Z to 2024-03-15T10:00:00Z"
    },
    "projected_impact": {
      "if_continued": 4200.00,
      "currency": "USD",
      "vs_normal": "+180%"
    }
  }
}

Authentication & Security

HMAC-SHA256 Signature Verification

All webhook requests include an HMAC signature in the X-Webhook-Signature header. Verify this to ensure requests are authentic: Header format:
X-Webhook-Signature: t=1709294400,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Verification code (Node.js):
import crypto from 'crypto';

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const [timestampPart, signaturePart] = signature.split(',');
  const timestamp = timestampPart.split('=')[1];
  const expectedSignature = signaturePart.split('=')[1];

  const signedPayload = `${timestamp}.${payload}`;
  const computedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(computedSignature)
  );
}

// Usage in your webhook handler
app.post('/webhooks/billing', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const rawBody = JSON.stringify(req.body);

  if (!verifyWebhookSignature(rawBody, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook event
  const event = req.body;
  console.log(`Received ${event.type} for customer ${event.data.customer_id}`);
  res.json({ received: true });
});
Python verification:
import hmac
import hashlib
import time

def verify_webhook_signature(payload: str, signature: str, secret: str) -> bool:
    timestamp, expected_sig = signature.split(',')
    timestamp = timestamp.split('=')[1]
    expected_sig = expected_sig.split('=')[1]

    signed_payload = f"{timestamp}.{payload}"
    computed_sig = hmac.new(
        secret.encode('utf-8'),
        signed_payload.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected_sig, computed_sig)

Replay Attack Prevention

Check the timestamp to prevent replay attacks:
const MAX_TIMESTAMP_AGE = 5 * 60; // 5 minutes

function isTimestampValid(timestamp: string): boolean {
  const currentTime = Math.floor(Date.now() / 1000);
  const eventTime = parseInt(timestamp, 10);
  return Math.abs(currentTime - eventTime) <= MAX_TIMESTAMP_AGE;
}

Common Integration Patterns

1. Stripe Integration

Forward billing events to Stripe for invoice generation:
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

app.post('/webhooks/billing', async (req, res) => {
  const event = req.body;

  if (event.type === 'billing.period_end') {
    const { customer_id, summary, breakdown, period } = event.data;

    // Create Stripe invoice
    const invoice = await stripe.invoices.create({
      customer: customer_id,
      collection_method: 'charge_automatically',
      metadata: {
        pricing_model_id: event.data.pricing_model.model_id,
        period_start: period.start,
        period_end: period.end
      }
    });

    // Add line items from breakdown
    for (const item of breakdown) {
      await stripe.invoiceItems.create({
        customer: customer_id,
        invoice: invoice.id,
        amount: Math.round(item.amount * 100), // Stripe uses cents
        currency: summary.currency.toLowerCase(),
        description: `${item.display_name} (${item.usage.raw_value.toLocaleString()} ${item.usage.unit})`
      });
    }

    // Add platform fee
    if (summary.subtotals.platform_fees_total > 0) {
      await stripe.invoiceItems.create({
        customer: customer_id,
        invoice: invoice.id,
        amount: Math.round(summary.subtotals.platform_fees_total * 100),
        currency: summary.currency.toLowerCase(),
        description: 'Platform Fee'
      });
    }

    // Finalize and send
    await stripe.invoices.finalizeInvoice(invoice.id);
    console.log(`Stripe invoice created: ${invoice.id}`);
  }

  res.json({ received: true });
});

2. Threshold Alerts to Slack

Notify your team when customers hit usage limits:
import { WebClient } from '@slack/web-api';
const slack = new WebClient(process.env.SLACK_BOT_TOKEN);

app.post('/webhooks/billing', async (req, res) => {
  const event = req.body;

  if (event.type === 'billing.threshold_reached') {
    const { customer_id, threshold, usage_snapshot } = event.data;

    await slack.chat.postMessage({
      channel: '#billing-alerts',
      text: `🚨 Customer ${customer_id} reached ${threshold.currency} ${threshold.current_value} (limit: ${threshold.limit})`,
      blocks: [
        {
          type: 'section',
          text: {
            type: 'mrkdwn',
            text: `*Billing Threshold Alert*\n\nCustomer: \`${customer_id}\`\nCurrent spend: *$${threshold.current_value}*\nThreshold: $${threshold.limit}`
          }
        },
        {
          type: 'section',
          fields: [
            { type: 'mrkdwn', text: `*Sessions:*\n${usage_snapshot.sessions.toLocaleString()}` },
            { type: 'mrkdwn', text: `*Spans:*\n${usage_snapshot.spans.toLocaleString()}` },
            { type: 'mrkdwn', text: `*Tokens:*\n${usage_snapshot.tokens.toLocaleString()}` }
          ]
        }
      ]
    });
  }

  res.json({ received: true });
});

3. Custom Billing Database

Store billing events for internal reporting:
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();

app.post('/webhooks/billing', async (req, res) => {
  const event = req.body;

  if (event.type === 'billing.period_end') {
    const { customer_id, period, summary, breakdown } = event.data;

    // Store invoice
    const invoice = await prisma.invoice.create({
      data: {
        customer_id,
        period_start: new Date(period.start),
        period_end: new Date(period.end),
        total_amount: summary.total_amount,
        currency: summary.currency,
        pricing_model_id: event.data.pricing_model.model_id,
        pricing_model_version: event.data.pricing_model.version,
        status: 'pending',
        line_items: {
          create: breakdown.map(item => ({
            rule_id: item.rule_id,
            description: item.display_name,
            quantity: item.usage.raw_value,
            unit: item.usage.unit,
            amount: item.amount
          }))
        }
      }
    });

    console.log(`Invoice ${invoice.id} stored for customer ${customer_id}`);
  }

  res.json({ received: true });
});

Prerequisites & Setup Checklist

Before enabling billing webhooks, ensure your system has:

✅ Customer ID Tagging

Every telemetry record must include customer_id:
// ❌ Bad: No customer_id
telemetry.track({
  type: "span",
  span_id: "span_123"
});

// ✅ Good: Includes customer_id
telemetry.track({
  type: "span",
  span_id: "span_123",
  customer_id: "cust_acme_corp"  // ← Required
});
Implementation approaches:
  • Add customer_id in your SDK/library initialization
  • Use middleware to inject customer_id from auth context
  • Decorate at ingestion time using API keys or auth tokens

✅ Pricing Model Assignment

Each customer needs an active pricing model. Store this in a state table: Database schema example:
CREATE TABLE customer_pricing (
  customer_id VARCHAR(255) PRIMARY KEY,
  pricing_model_id VARCHAR(255) NOT NULL,
  pricing_model_version VARCHAR(50) NOT NULL,
  activated_at TIMESTAMP NOT NULL,
  metadata JSONB
);
API to assign pricing model:
await client.customers.setPricingModel({
  customerId: "cust_acme_corp",
  modelId: "plan_ent_premium_001"
});

✅ Webhook Endpoint

Your server must expose a POST endpoint to receive events:
// Express.js example
app.post('/webhooks/billing',
  express.raw({ type: 'application/json' }), // Important: raw body for signature verification
  async (req, res) => {
    try {
      const event = JSON.parse(req.body.toString());

      // Verify signature
      const signature = req.headers['x-webhook-signature'];
      if (!verifyWebhookSignature(req.body.toString(), signature, process.env.WEBHOOK_SECRET)) {
        return res.status(401).json({ error: 'Invalid signature' });
      }

      // Process event
      await handleBillingEvent(event);

      res.json({ received: true });
    } catch (error) {
      console.error('Webhook error:', error);
      res.status(500).json({ error: 'Webhook processing failed' });
    }
  }
);
Critical: Always respond with 200 OK within 5 seconds to prevent webhook retries. Process heavy operations (Stripe API calls, database writes) asynchronously using a job queue.

✅ Idempotency Handling

Webhooks may be delivered multiple times. Implement idempotency:
async function handleBillingEvent(event: BillingEvent) {
  // Check if we've already processed this event
  const existing = await prisma.processedWebhook.findUnique({
    where: { event_id: event.id }
  });

  if (existing) {
    console.log(`Event ${event.id} already processed, skipping`);
    return;
  }

  // Process event
  await processBillingEvent(event);

  // Mark as processed
  await prisma.processedWebhook.create({
    data: {
      event_id: event.id,
      event_type: event.type,
      processed_at: new Date()
    }
  });
}

Testing & Debugging

Shadow Mode Testing

Before going live, run your pricing model in shadow mode:
await client.pricingModels.update({
  modelId: "plan_ent_premium_001",
  status: "shadow"  // Generates reports but doesn't trigger billing webhooks
});

// Run simulations to verify calculations
const result = await client.simulations.run({
  modelId: "plan_ent_premium_001",
  customerId: "cust_test_001",
  timeRange: {
    start: "2024-03-01T00:00:00Z",
    end: "2024-03-31T23:59:59Z"
  }
});

console.log(`Shadow mode revenue: $${result.summary.total_amount}`);

Webhook Test Events

Send test events to your endpoint:
curl -X POST https://api.yourplatform.com/v1/billing/webhooks/wh_stripe_prod/test \
  -H "Authorization: Bearer your_api_key"

Local Development with Webhook Forwarding

Use tools like ngrok or cloudflared to forward webhooks to localhost:
# Using ngrok
ngrok http 3000

# Update webhook URL to ngrok URL
curl -X PATCH https://api.yourplatform.com/v1/billing/webhooks/wh_stripe_prod \
  -H "Authorization: Bearer your_api_key" \
  -d '{"url": "https://abc123.ngrok.io/webhooks/billing"}'

Webhook Logs

View webhook delivery history and debug failures: Endpoint: GET /billing/webhooks/{webhook_id}/deliveries
{
  "data": [
    {
      "delivery_id": "del_001",
      "event_type": "billing.period_end",
      "status": "success",
      "response_code": 200,
      "delivered_at": "2024-03-31T23:59:59Z",
      "latency_ms": 245
    },
    {
      "delivery_id": "del_002",
      "event_type": "billing.threshold_reached",
      "status": "failed",
      "response_code": 500,
      "error": "Internal server error",
      "delivered_at": "2024-03-15T14:23:45Z",
      "retry_count": 3
    }
  ]
}

Retry Failed Webhooks

Manually retry failed webhook deliveries:
curl -X POST https://api.yourplatform.com/v1/billing/webhooks/deliveries/del_002/retry \
  -H "Authorization: Bearer your_api_key"

Billing API Reference

Webhook Management

Create Webhook

Endpoint: POST /billing/webhooks Request:
{
  "name": "Production Stripe Webhook",
  "url": "https://api.yourcompany.com/webhooks/billing",
  "events": ["billing.period_end", "billing.threshold_reached"],
  "auth": {
    "type": "hmac_sha256",
    "secret": "whsec_your_webhook_secret"
  }
}
Response: 201 Created
{
  "webhook_id": "wh_abc123",
  "status": "active",
  "created_at": "2024-03-01T10:00:00Z"
}

List Webhooks

Endpoint: GET /billing/webhooks Response: 200 OK
{
  "data": [
    {
      "webhook_id": "wh_abc123",
      "name": "Production Stripe Webhook",
      "url": "https://api.yourcompany.com/webhooks/billing",
      "events": ["billing.period_end", "billing.threshold_reached"],
      "status": "active",
      "last_delivery_at": "2024-03-31T23:59:59Z",
      "success_rate": 99.2
    }
  ]
}

Update Webhook

Endpoint: PATCH /billing/webhooks/{webhook_id} Request:
{
  "events": ["billing.period_end", "billing.threshold_reached", "billing.usage_spike"],
  "status": "active"
}

Delete Webhook

Endpoint: DELETE /billing/webhooks/{webhook_id} Response: 200 OK

Billing Triggers

Create Period-Based Trigger

Endpoint: POST /billing/triggers Request:
{
  "trigger_type": "period_end",
  "schedule": {
    "frequency": "monthly",
    "day_of_month": 1,
    "timezone": "America/Los_Angeles"
  },
  "pricing_model_id": "plan_ent_premium_001",
  "webhook_ids": ["wh_abc123"]
}

Create Threshold Trigger

Endpoint: POST /billing/triggers Request:
{
  "trigger_type": "threshold_reached",
  "threshold": {
    "metric": "total_amount",
    "value": 500.00,
    "currency": "USD"
  },
  "pricing_model_id": "plan_ent_premium_001",
  "webhook_ids": ["wh_abc123"],
  "notification_channels": ["webhook", "email"]
}

Create Usage Spike Trigger

Endpoint: POST /billing/triggers Request:
{
  "trigger_type": "usage_spike",
  "spike_config": {
    "multiplier": 2.0,
    "baseline_period": "7d",
    "cooldown": "1h"
  },
  "pricing_model_id": "plan_ent_premium_001",
  "webhook_ids": ["wh_slack_alerts"]
}

Customer Billing Management

Assign Pricing Model to Customer

Endpoint: POST /billing/customers/{customer_id}/pricing-model Request:
{
  "pricing_model_id": "plan_ent_premium_001",
  "effective_date": "2024-04-01T00:00:00Z",
  "metadata": {
    "contract_id": "contract_123",
    "sales_rep": "alice@company.com"
  }
}

Get Customer Billing Status

Endpoint: GET /billing/customers/{customer_id}/status Response: 200 OK
{
  "customer_id": "cust_acme_corp",
  "pricing_model": {
    "model_id": "plan_ent_premium_001",
    "version": "1.2.0",
    "activated_at": "2024-03-01T00:00:00Z"
  },
  "current_period": {
    "start": "2024-03-01T00:00:00Z",
    "end": "2024-03-31T23:59:59Z",
    "days_remaining": 5
  },
  "usage_to_date": {
    "sessions": 28500,
    "spans": 2850000,
    "tokens": 285000000
  },
  "projected_bill": {
    "amount": 875.00,
    "currency": "USD",
    "based_on": "current_usage_rate"
  },
  "thresholds": [
    {
      "metric": "total_amount",
      "limit": 500.00,
      "current": 520.00,
      "status": "exceeded",
      "exceeded_at": "2024-03-15T14:23:45Z"
    }
  ]
}

Best Practices

Never trust webhook payloads without signature verification. Implement HMAC-SHA256 verification and check timestamp freshness to prevent replay attacks.
Respond with 200 OK within 5 seconds to prevent retries. Use job queues (Celery, Bull, SQS) for heavy operations like Stripe API calls or database writes.
Webhooks can be delivered multiple times. Always check if you’ve already processed an event_id before taking action. Store processed event IDs in your database.
Before activating billing, run your pricing model in shadow mode for at least one full billing cycle. Verify calculations match expectations.
Track webhook delivery success rates and latency. Alert on success rates below 95% or sudden spikes in failures. This often indicates endpoint issues.
Ensure every span, session, and event includes customer_id at ingestion time. Missing customer_id means unbillable usage—that’s lost revenue.
Configure threshold alerts at 50%, 80%, and 100% of expected monthly spend. This prevents surprise bills and gives customers visibility into usage.
When changing pricing, create a new version rather than modifying the active model. This creates an audit trail and makes rollbacks easy.

Troubleshooting

Webhooks Not Firing

Problem: Activated pricing model but no webhooks are sent. Solutions:
  1. Verify pricing model status is “active” (not “shadow” or “draft”)
  2. Check webhook status is “active” in /billing/webhooks
  3. Confirm telemetry records have customer_id field
  4. Review webhook delivery logs: GET /billing/webhooks/{webhook_id}/deliveries

Missing Customer ID

Problem: Telemetry data exists but billing calculations return $0. Solutions:
  1. Query telemetry data: SELECT COUNT(*) FROM spans WHERE customer_id IS NULL
  2. Update SDK/library to include customer_id in all tracking calls
  3. Add middleware to inject customer_id from auth context
  4. Backfill historical data if possible (contact support for bulk update)

Webhook Signature Verification Fails

Problem: Endpoint returns 401 “Invalid signature”. Solutions:
  1. Ensure you’re using raw request body (not parsed JSON) for signature verification
  2. Check webhook secret matches dashboard value
  3. Verify timestamp is within 5 minutes (prevent replay attacks)
  4. Test with sample payload: POST /billing/webhooks/{webhook_id}/test

Duplicate Invoices

Problem: Same billing period generates multiple invoices. Solutions:
  1. Implement idempotency: check if event.id was already processed
  2. Store processed event IDs in database with unique constraint
  3. Respond with 200 OK even if already processed (prevents retries)

Usage Spike False Positives

Problem: Spike alerts triggered during expected high usage (e.g., product launch). Solutions:
  1. Adjust baseline_period to include recent high-usage days
  2. Increase multiplier from 2.0x to 3.0x or higher
  3. Add cooldown period to prevent alert spam
  4. Temporarily disable trigger: PATCH /billing/triggers/{trigger_id} {"status": "paused"}

Next Steps

Pro tip: Set up billing webhooks early, even if you’re not charging customers yet. Running in shadow mode lets you validate your billing logic with real usage data before going live.