---
name: Lago
description: Use when building or managing usage-based billing systems, configuring subscription and metered pricing models, ingesting customer usage events, generating invoices, or integrating payment providers. Agents should reach for this skill when working with billing architecture, pricing configuration, customer management, or revenue recognition workflows.
metadata:
    mintlify-proj: lago
    version: "1.0"
---

# Lago Skill Reference

## Product summary

Lago is an open-source, event-driven billing platform for usage-based and subscription billing. It turns customer usage events into accurate invoices through a five-step workflow: ingest events → aggregate into billable metrics → define pricing via plans → generate invoices → collect payments. Agents use Lago's REST API (base URL: `https://api.getlago.com/api/v1` for Cloud, or self-hosted instance URL) with Bearer token authentication. Key files and concepts: billable metrics (aggregation rules), plans (pricing models), subscriptions (customer + plan), invoices (generated automatically), and events (usage data). Primary docs: https://docs.getlago.com

## When to use

Reach for this skill when:
- **Building billing infrastructure**: Setting up usage-based pricing, subscription models, or hybrid billing (fixed + metered)
- **Configuring pricing**: Creating billable metrics, defining charge models (standard, graduated, volume, package, percentage), applying filters for dimension-based pricing
- **Managing customers**: Creating customer records, assigning plans, tracking usage, monitoring billing status
- **Ingesting usage**: Designing event schemas, sending events via REST API/batch/Kafka/S3, handling deduplication and late arrivals
- **Invoice workflows**: Generating invoices, managing draft/finalized states, applying taxes, handling credit notes, voiding invoices
- **Payment integration**: Connecting Stripe, Adyen, GoCardless, or custom payment providers; managing payment methods and retries
- **Troubleshooting billing**: Debugging charge calculations, reconciling usage, fixing invoice errors, handling edge cases

## Quick reference

### Core API endpoints

| Task | Endpoint | Method |
|------|----------|--------|
| Create customer | `/customers` | POST |
| Create billable metric | `/billable_metrics` | POST |
| Create plan | `/plans` | POST |
| Assign plan to customer | `/subscriptions` | POST |
| Send usage event | `/events` | POST |
| Batch events | `/events/batch` | POST |
| Get current usage | `/customers/{id}/current_usage` | GET |
| Create invoice | `/invoices/create_oneoff` | POST |
| Finalize invoice | `/invoices/{id}/finalize` | PUT |
| Get invoice | `/invoices/{id}` | GET |

### Authentication

```bash
LAGO_URL="https://api.getlago.com"  # or your self-hosted URL
API_KEY="__YOUR_API_KEY__"

curl -H "Authorization: Bearer $API_KEY" \
     -H "Content-Type: application/json" \
     "$LAGO_URL/api/v1/..."
```

Retrieve API key from Dashboard → Developers → API keys. Rotate keys via the same section; old key becomes inactive immediately.

### Billable metric aggregation types

| Type | Use case | Recurring? |
|------|----------|-----------|
| `count_agg` | Count events (API calls, transactions) | Metered |
| `unique_count_agg` | Count unique values (users, sessions) | Metered or Recurring |
| `sum_agg` | Sum property values (GB, tokens, amount) | Metered or Recurring |
| `max_agg` | Peak value in period (max CPU, max storage) | Metered |
| `latest_agg` | Last value in period | Metered |
| `weighted_sum_agg` | Sum prorated by time used | Metered or Recurring |

### Charge models

| Model | When to use | Example |
|-------|------------|---------|
| `standard` | Flat per-unit pricing | $0.10 per API call |
| `graduated` | Tiered pricing, each tier has own rate | First 100 @ $1, next 100 @ $0.50 |
| `volume` | Single rate based on total volume | 65K units @ $0.0006/unit (tier 3 rate) |
| `package` | Fixed price per bundle of units | $5 per 100 units, first 100 free |
| `percentage` | Percentage of transaction amount | 2.9% + $0.30 per transaction |
| `graduated_percentage` | Tiered percentage rates | First $1K @ 3%, next @ 2% |
| `dynamic` | Custom expression-based pricing | `properties.tokens_in + properties.tokens_out` |

### Event schema (required fields)

```json
{
  "transaction_id": "txn_20240314_cust42_api_00001",
  "external_subscription_id": "sub_42",
  "code": "api_calls",
  "timestamp": 1710421740,
  "properties": {
    "endpoint": "/search",
    "tokens": 1500
  }
}
```

- `transaction_id`: Unique ID for deduplication (deterministic, not random)
- `external_subscription_id`: Links to customer's subscription
- `code`: Billable metric code
- `timestamp`: Unix seconds (or milliseconds with decimal); defaults to ingestion time if omitted
- `properties`: Dimensions for pricing (optional but recommended for flexibility)

### Invoice lifecycle

| Status | Meaning | Editable? |
|--------|---------|-----------|
| `draft` | In grace period, events can be added | Yes |
| `finalized` | Issued, numbered, locked | No |
| `voided` | Finalized then voided (keeps record) | No |
| `failed` | Tax sync or finalization error | Retry only |
| `deleted` | Draft deleted before finalization | No (removed entirely) |

## Decision guidance

### When to use REST API vs. batch vs. streaming

| Volume | Delivery | Latency | Setup |
|--------|----------|---------|-------|
| < 1K events/sec | REST API (single) | Real-time | Minimal |
| 1K–10K events/sec | REST API (batch) or Kafka | Real-time | Moderate |
| > 10K events/sec | Kafka / Kinesis / S3 | Real-time or batch | Complex |
| Historical backfill | S3 (JSONL) | Batch | Moderate |

**Start with REST API.** Migrate to Kafka only when you outgrow it.

### When to use calendar vs. anniversary billing

| Scenario | Choice | Behavior |
|----------|--------|----------|
| Standard SaaS (month-end billing) | Calendar | All customers billed on same day each month |
| Custom contract dates | Anniversary | Customer billed on signup date each month |
| Mixed requirements | Both | Different subscriptions can use different cycles |

### When to finalize vs. void vs. delete invoices

| Action | When | Result |
|--------|------|--------|
| Finalize | End of grace period or manually | Invoice gets number, locked, payment due |
| Void | After finalized, need to cancel | Keeps numbered record, shows as voided |
| Delete | Draft only, before finalization | Removes entirely, no record left |

Use **delete** for mistakes caught early. Use **void** for invoices already issued to customers.

### When to use filters vs. groups vs. custom expressions

| Need | Approach | Example |
|------|----------|---------|
| Different rates by region | Charge filters | `region: ["US", "EU"]` with different amounts |
| Display breakdown on invoice | Pricing groups | Group by `instance_type` for visibility |
| Complex calculation | Custom expression | `properties.tokens_in + properties.tokens_out` |

## Workflow

### 1. Set up billing infrastructure

1. **Create billable metrics** for each chargeable feature:
   - Decide aggregation type (count, sum, unique_count, max, latest, weighted_sum)
   - Set `code` (used in events), `field_name` (property to aggregate), `recurring` (true if carries over periods)
   - Add filters if pricing varies by dimension (region, instance type, etc.)

2. **Create plans** with pricing:
   - Set base subscription fee, billing interval (monthly/yearly), advance vs. arrears
   - Add usage-based charges linked to billable metrics
   - Define charge model and pricing properties (tiers, rates, free units)
   - Add fixed charges (add-ons) if needed
   - Apply taxes at plan or charge level

3. **Create customers**:
   - Set `external_id` (your system's customer ID), name, billing address
   - Assign default payment provider and currency
   - Add metadata if needed

### 2. Assign subscriptions and start billing

1. **Assign plan to customer**:
   - POST `/subscriptions` with `external_customer_id`, `plan_code`, `subscription_at` (start date)
   - Optionally set `ending_at` for fixed-term contracts
   - Choose `billing_time`: `calendar` (month-end) or `anniversary` (signup date)
   - Optionally override plan pricing per customer (premium feature)

2. **Verify subscription is active**:
   - Check subscription status in dashboard or via GET `/subscriptions/{id}`
   - Confirm billing period and next invoice date

### 3. Ingest usage events

1. **Design event schema**:
   - Identify what you charge for (API calls, GB, tokens, transactions)
   - Decide what dimensions you price on (region, model, tier)
   - Include those dimensions in `properties`

2. **Send events**:
   - **Single event**: POST `/events` with one event object
   - **Batch**: POST `/events/batch` with up to 100 events (atomic: all succeed or all fail)
   - **Streaming**: Kafka/Kinesis for high volume (requires ClickHouse event store)
   - **Backfill**: S3 JSONL files for historical data

3. **Verify ingestion**:
   - GET `/events/{transaction_id}` to confirm event was received
   - GET `/customers/{id}/current_usage` to see aggregated usage for current period

### 4. Generate and manage invoices

1. **Invoices are generated automatically**:
   - At end of billing period (or on schedule for advance-billed subscriptions)
   - Status starts as `draft` (grace period for edits)
   - Webhook `invoice.created` fires when draft is generated

2. **During draft period** (grace period):
   - Add missing events (late arrivals)
   - Manually add/edit fees
   - Apply coupons or credits
   - Refresh if taxes need recalculation

3. **Finalize invoice**:
   - Manually: PUT `/invoices/{id}/finalize` before grace period ends
   - Automatically: After grace period expires
   - Invoice gets number, locked, payment status becomes `pending`

4. **Handle payment**:
   - If payment provider connected: Lago triggers payment intent automatically
   - If manual: Record payment via POST `/payments`
   - If failed: Retry via payment retry logic or dunning workflow

### 5. Reconcile and adjust

1. **Issue credit notes** for refunds or adjustments:
   - POST `/credit_notes` with reason and amount
   - Applies to customer's next invoice

2. **Void invoices** if already finalized:
   - PUT `/invoices/{id}/void`
   - Keeps numbered record, shows as voided

3. **Monitor analytics**:
   - GET `/analytics/gross_revenue` for customer revenue
   - GET `/analytics/overdue_balance` for collection status
   - Dashboard reports for MRR, churn, usage trends

## Common gotchas

- **Events sent before subscription starts are ignored**: Verify `subscription_at` date is before or equal to event `timestamp`. Late-arriving events are assigned to correct historical period based on `timestamp`, not arrival time.

- **Duplicate transaction_ids are rejected on Postgres, replaced on ClickHouse**: On Postgres, sending the same `transaction_id` twice returns a 422 error. On ClickHouse, the latest copy replaces the earlier one. Always send `timestamp` explicitly on ClickHouse to avoid retries creating new billable events.

- **Charge configuration changes apply to current open period only**: Updating a charge's pricing reprices all usage in the current period, even events received earlier. Finalize the invoice before changing pricing to lock amounts.

- **Billable metric code is a contract**: If you rename a metric, events sent with the old code won't match. Create a new metric with the new code; old events stay linked to the old metric.

- **Events for non-existent subscriptions are ingested but not billed**: If `external_subscription_id` doesn't match an active subscription, the event is stored but skipped during aggregation. No error is raised.

- **Filters are case-sensitive**: Filter values in events must match exactly. `"region": "AWS"` won't match a filter expecting `"aws"`.

- **Recurring metrics carry over; metered metrics reset**: A `recurring: true` metric keeps its value across periods. A `recurring: false` metric resets to 0 at period end. Choose carefully for per-seat or per-user billing.

- **Draft invoices can't be edited after finalization**: Once finalized, you can only void (keep record) or create a credit note. You can't add events or adjust fees.

- **Taxes are calculated at finalization**: If using Avalara or Anrok, taxes are fetched when the invoice is finalized. If the tax provider is down, the invoice enters `failed` status and must be retried.

- **Plan overrides are premium feature**: Customizing pricing per customer requires a premium license. Contact sales for access.

- **Subscription consolidation is automatic by default**: Multiple subscriptions billed on the same day to the same customer are consolidated into one invoice. Set `consolidate_invoices: false` on the subscription to keep it separate.

- **Deleting a customer terminates all subscriptions**: Deleting a customer immediately terminates active subscriptions and may generate invoices/credit notes. Finalized invoices remain in records.

## Verification checklist

Before submitting billing work:

- [ ] **Events**: Verify `transaction_id` is deterministic (not random UUID), `external_subscription_id` matches an active subscription, `code` matches a billable metric, `timestamp` is explicit (not relying on ingestion time)
- [ ] **Billable metrics**: Confirm aggregation type matches use case (count for events, sum for amounts, unique_count for users), `field_name` exists in event properties, filters are case-sensitive and match event values
- [ ] **Plans**: Check charge model is correct (standard for flat, graduated for tiers, volume for total-based), pricing properties are complete (tiers, rates, free units), taxes are applied at plan or charge level as intended
- [ ] **Subscriptions**: Verify `subscription_at` is before or equal to first event timestamp, `billing_time` is set (calendar or anniversary), plan is not locked (can still add/remove charges if needed)
- [ ] **Invoices**: Confirm draft period allows time for edits, grace period is set appropriately, taxes are calculated (no `failed` status), payment provider is connected if auto-payment is needed
- [ ] **Payments**: Check payment method is set on customer, payment provider credentials are valid, payment retries are configured if needed
- [ ] **Testing**: Send a single test event via REST API, verify it appears in GET `/events/{transaction_id}`, check current usage via GET `/customers/{id}/current_usage`, generate a test invoice and verify amounts

## Resources

**Comprehensive navigation**: https://docs.getlago.com/llms.txt

**Critical pages**:
- [Welcome to Lago](https://docs.getlago.com/guide/introduction/welcome-to-lago) — Five-step billing workflow overview
- [Ingest usage](https://docs.getlago.com/guide/events/ingesting-usage) — Event design, delivery methods, deduplication, edge cases
- [API Reference](https://docs.getlago.com/api-reference/intro) — Complete endpoint documentation with examples in multiple languages

---

> For additional documentation and navigation, see: https://docs.getlago.com/llms.txt