<!-- Copyright (c) 2026 Todd Levy. Licensed under MIT. SPDX-License-Identifier: MIT -->
OpenMeter API
Project-agnostic reference for the OpenMeter REST API. Organized by the official API tags from the OpenAPI 3.0 spec.
Suite
| Skill | Purpose |
|---|
| tl-openmeter-api | This skill: REST API reference |
| tl-openmeter-local-dev | Local dev setup: Docker, ngrok, Stripe App, webhooks |
| tl-openmeter-api-mcp-server | MCP server for calling local OpenMeter from Cursor |
When to Use
- "How do I ingest events into OpenMeter?"
- "Create an OpenMeter customer with subscription"
- "Query usage for a meter"
- "Set up notification rules for threshold alerts"
- "Manage billing invoices"
- "Install the Stripe marketplace app"
- Debugging metering, billing, or subscription lifecycle
Resources
Official API Tags
The OpenMeter API organizes endpoints into these 15 tags:
| # | Tag | Description |
|---|
| 1 | Apps | Manage app integrations (list, get, update, uninstall) |
| 2 | App: Custom Invoicing | Interface third-party invoicing and payment systems |
| 3 | App: Stripe | Stripe billing support (API key, webhook, checkout) |
| 4 | Billing | Billing profiles, invoices, customer overrides, pending lines |
| 5 | Customers | Customer lifecycle, app data, Stripe linking, entitlement values |
| 6 | Debug | Internal metrics (Prometheus format) |
| 7 | Entitlements | Usage limits, quota-based pricing, feature access |
| 8 | Events | CloudEvents ingestion and listing |
| 9 | Lookup Information | Static data (currencies, progress) |
| 10 | Meters | Aggregation rules, usage queries, group-by |
| 11 | Notifications | Channels, rules, events for threshold alerts |
| 12 | Portal | Consumer-facing usage dashboards via scoped tokens |
| 13 | Product Catalog | Plans, features, addons (versioning, rate cards, publish lifecycle) |
| 14 | Subjects | Deprecated — use Customers with usageAttribution.subjectKeys |
| 15 | Subscriptions | Customer plan assignments, cancel, change, migrate, restore |
Base URL and Auth
- Base URL:
OPENMETER_URL (e.g. http://localhost:8888 for local, or your deployed URL) - Auth:
Authorization: Bearer <OPENMETER_API_KEY>. Local self-hosted often runs unauthenticated. - Content-Type:
application/json for most endpoints; application/cloudevents+json for POST /api/v1/events
Concepts
Meter (aggregates events) → Feature (metered entitlement) → Plan (limits + pricing)
↓
Customer (subject keys) ←→ Subscription (customer + plan = active entitlements)
↓
Billing Profile → Invoices (via Stripe/Sandbox/Custom App)
- Meter: Aggregation rule for events (COUNT, SUM, etc.). Events reference a meter via
type matching eventType. - Feature: Tied to a meter or boolean; used in plan rate cards for quotas and overage.
- Plan: Contains phases and rate cards. Part of the Product Catalog alongside Features and Addons.
- Addon: Modular rate card bundle, attachable to plans or subscriptions.
- Customer: Has
usageAttribution.subjectKeys; event subject must match for usage to attach. - Subscription: Links customer to plan; active subscription grants entitlements.
- Entitlement: Per-customer access to a feature with usage tracking and limits.
- Grant: One-time credit or usage allocation against an entitlement.
- Notification: Automated alert when entitlement thresholds are reached.
- App: Billing provider integration (Stripe, Sandbox, Custom Invoicing).
1. Events
Ingest: POST /api/v1/events | Content-Type: application/cloudevents+json
json{
"specversion": "1.0",
"id": "unique-event-id",
"type": "api_request",
"source": "my-app",
"subject": "user_abc123",
"time": "2026-02-14T12:00:00Z",
"data": { "value": 1, "path": "/v1/events", "method": "GET" }
}
| Field | Required | Notes |
|---|
type | Yes | Must match meter's eventType |
subject | Yes | Must match customer's usageAttribution.subjectKeys |
source | Yes | Identifies the producing system |
id | Yes | Idempotency key (deduplication within 24h) |
time | Recommended | ISO 8601 timestamp |
data | Recommended | Arbitrary payload; meters use $.path for groupBy |
List events: GET /api/v1/events?from=...&to=...&subject=...&hasError=...
2. Meters
| Operation | Method | Path |
|---|
| List | GET | /api/v1/meters |
| Create | POST | /api/v1/meters |
| Get | GET | /api/v1/meters/{meterIdOrSlug} |
| Update | PUT | /api/v1/meters/{meterIdOrSlug} |
| Delete | DELETE | /api/v1/meters/{meterIdOrSlug} |
| Query usage | GET | /api/v1/meters/{meterIdOrSlug}/query?subject=...&from=...&to=...&windowSize=HOUR |
| Query (POST) | POST | /api/v1/meters/{meterIdOrSlug}/query |
| Group-by values | GET | /api/v1/meters/{meterIdOrSlug}/group-by/{groupBy}/values |
| List subjects | GET | /api/v1/meters/{meterIdOrSlug}/subjects |
Aggregation types: COUNT, SUM, AVG, MIN, MAX, UNIQUE_COUNT
Window sizes: MINUTE, HOUR, DAY, MONTH
3. Product Catalog
Plans, Features, and Addons all live under this tag. See references/product-catalog.md for versioning lifecycle, rate cards, and detailed examples.
Features
| Operation | Method | Path |
|---|
| List | GET | /api/v1/features |
| Create | POST | /api/v1/features |
| Get | GET | /api/v1/features/{featureId} |
| Delete | DELETE | /api/v1/features/{featureId} |
Plans
| Operation | Method | Path |
|---|
| List | GET | /api/v1/plans |
| Create | POST | /api/v1/plans |
| Get | GET | /api/v1/plans/{planIdOrKey} |
| Update | PUT | /api/v1/plans/{planIdOrKey} |
| Delete | DELETE | /api/v1/plans/{planIdOrKey} |
| Next version | POST | /api/v1/plans/{planIdOrKey}/next |
| Publish | POST | /api/v1/plans/{planIdOrKey}/publish |
| Archive | POST | /api/v1/plans/{planIdOrKey}/archive |
| Plan Addons | CRUD | /api/v1/plans/{planIdOrKey}/addons/... |
Addons
| Operation | Method | Path |
|---|
| List | GET | /api/v1/addons |
| Create | POST | /api/v1/addons |
| Get | GET | /api/v1/addons/{addonIdOrKey} |
| Update | PUT | /api/v1/addons/{addonIdOrKey} |
| Delete | DELETE | /api/v1/addons/{addonIdOrKey} |
| Publish | POST | /api/v1/addons/{addonIdOrKey}/publish |
| Archive | POST | /api/v1/addons/{addonIdOrKey}/archive |
Critical: Plan/addon keys must be snakecase (`^[a-z0-9]+(?:[a-z0-9]+)*$). Rate card upToAmount must be a string. Subscription creation uses plan: { "key": "plan_key" }`, not a raw planId. Plans follow a draft -> published -> archived lifecycle.
4. Customers
| Operation | Method | Path |
|---|
| List | GET | /api/v1/customers?page=...&pageSize=...&subject=...&planKey=... |
| Create | POST | /api/v1/customers |
| Get | GET | /api/v1/customers/{customerIdOrKey} |
| Delete | DELETE | /api/v1/customers/{id} |
| Get access | GET | /api/v1/customers/{id}/access |
| Subscriptions | GET | /api/v1/customers/{id}/subscriptions |
| Entitlement value | GET | /api/v1/customers/{id}/entitlements/{featureKey}/value |
| Stripe data | GET/PUT | /api/v1/customers/{id}/stripe |
| Stripe portal | POST | /api/v1/customers/{id}/stripe/portal |
| App data | GET/PUT/DELETE | /api/v1/customers/{id}/apps/{appIdOrType} |
Gotcha: DELETE returns 409 if customer has active subscriptions or non-final invoices. See references/billing.md for the customer delete flow.
5. Subscriptions
| Operation | Method | Path |
|---|
| Create | POST | /api/v1/subscriptions |
| Get | GET | /api/v1/subscriptions/{id} |
| Edit | PATCH | /api/v1/subscriptions/{id} |
| Delete | DELETE | /api/v1/subscriptions/{id} |
| Cancel | POST | /api/v1/subscriptions/{id}/cancel |
| Change plan | POST | /api/v1/subscriptions/{id}/change |
| Migrate | POST | /api/v1/subscriptions/{id}/migrate |
| Restore | POST | /api/v1/subscriptions/{id}/restore |
| Unschedule cancel | POST | /api/v1/subscriptions/{id}/unschedule-cancelation |
| Subscription addons | GET/POST | /api/v1/subscriptions/{id}/addons |
Subscription Customizations and Migration
See Subscriptions Deep Dive for the full PATCH customizations schema (additem / removeitem), the stretch_phase operation, subscription state allowed-operations matrix, and the legacy plan-version migration pattern.
6. Entitlements
| Operation | Method | Path |
|---|
| List all | GET | /api/v1/entitlements |
| Get by id | GET | /api/v1/entitlements/{id} |
| Per-customer value | GET | /api/v1/customers/{id}/entitlements/{featureKey}/value |
| History | GET | /api/v1/subjects/{subjectIdOrKey}/entitlements/{idOrKey}/history |
| Reset usage | POST | /api/v1/subjects/{subjectIdOrKey}/entitlements/{id}/reset |
| Override | PUT | /api/v1/subjects/{subjectIdOrKey}/entitlements/{idOrKey}/override |
| Grants | POST/GET/DELETE | /api/v1/subjects/.../entitlements/.../grants, /api/v1/grants/... |
7. Billing
See references/billing.md for invoice lifecycle, customer delete flow, and rate card schemas.
| Resource | Operations | Base Path |
|---|
| Profiles | List, Create, Get, Update, Delete | /api/v1/billing/profiles |
| Customer overrides | List, Upsert, Get, Delete | /api/v1/billing/profiles/{id}/customer-overrides |
| Invoices | List, Get, Update, Delete, Simulate | /api/v1/billing/invoices |
| Invoice actions | Advance, Approve, Retry, Void, Snapshot, Recalculate tax | POST on /api/v1/billing/invoices/{id}/{action} |
| Pending lines | Create, Invoice | /api/v1/billing/customers/{id}/invoices/pending-lines |
Invoice lifecycle: gathering → draft → issuing → issued → (paid | void | uncollectible)
8. Notifications
See references/notifications.md for channels, rules, and event details.
| Resource | Operations | Base Path |
|---|
| Channels | List, Create, Get, Update, Delete | /api/v1/notification/channels |
| Rules | List, Create, Get, Update, Delete, Test | /api/v1/notification/rules |
| Events | List, Get, Resend | /api/v1/notification/events |
Note: Channel creation via API is Cloud-only (Svix-backed). Self-hosted uses YAML config.
9. Apps
| Operation | Method | Path |
|---|
| List apps | GET | /api/v1/apps |
| Get app | GET | /api/v1/apps/{id} |
| Update app | PUT | /api/v1/apps/{id} |
| Uninstall | DELETE | /api/v1/apps/{id} |
App: Stripe
| Operation | Method | Path |
|---|
| Update Stripe key | PUT | /api/v1/apps/{id}/stripe/api-key |
| Stripe webhook | POST | /api/v1/apps/{id}/stripe/webhook |
| Checkout session | POST | /api/v1/stripe/checkout/sessions |
App: Custom Invoicing
| Operation | Method | Path |
|---|
| Draft synced | POST | /api/v1/apps/{id}/custom-invoicing/draft-synchronized |
| Issuing synced | POST | /api/v1/apps/{id}/custom-invoicing/issuing-synchronized |
| Update payment | POST | /api/v1/apps/{id}/custom-invoicing/update-payment-status |
Marketplace
| Operation | Method | Path |
|---|
| List listings | GET | /api/v1/marketplace/listings |
| Get listing | GET | /api/v1/marketplace/listings/{type} |
| Install (generic) | POST | /api/v1/marketplace/listings/{type}/install |
| Install (API key) | POST | /api/v1/marketplace/listings/{type}/install/apikey |
| Install (OAuth2 URL) | GET | /api/v1/marketplace/listings/{type}/install/oauth2 |
| Install (OAuth2 auth) | POST | /api/v1/marketplace/listings/{type}/install/oauth2/authorize |
10. Portal
| Operation | Method | Path |
|---|
| Create token | POST | /api/v1/portal/tokens |
| List tokens | GET | /api/v1/portal/tokens |
| Invalidate tokens | POST | /api/v1/portal/tokens/invalidate |
| Query meter | GET | /api/v1/portal/meters/{meterSlug}/query |
11. Lookup Information
| Operation | Method | Path |
|---|
| List currencies | GET | /api/v1/currencies |
| Get progress | GET | /api/v1/progress |
12. Debug
| Operation | Method | Path |
|---|
| Get metrics | GET | /api/v1/debug/metrics |
13. Subjects (Deprecated)
Use Customers with usageAttribution.subjectKeys instead.
| Operation | Method | Path |
|---|
| List | GET | /api/v1/subjects |
| Upsert | POST | /api/v1/subjects |
| Get | GET | /api/v1/subjects/{subjectIdOrKey} |
| Delete | DELETE | /api/v1/subjects/{subjectIdOrKey} |
Gotchas and Errors
| Symptom | Cause | Fix |
|---|
| 409 on DELETE customer | Active subscriptions or non-final invoices | Cancel subs, void/delete invoices first |
| 400 "single draft version" | Duplicate plan draft | Skip creation if plan key exists |
| 400 "only Plans in [draft scheduled] can be published" | Plan already active | Expected — skip publish |
| 500 on POST /notification/channels | Self-hosted: not implemented | Use YAML config for local; API for Cloud only |
| 405 on PATCH invoice | PATCH not supported | Use POST subpaths: /advance, /approve, /void |
| Usage not attributed | Subject mismatch | Event subject must match usageAttribution.subjectKeys |
| Plan not found | Wrong key format | Use snakecase: `pro`, `proplus` |
| Event not metered | Type mismatch | Event type must equal meter's eventType |
| Overage not billed | Tier format | upToAmount must be string; include both flatPrice and unitPrice |
IDs look like 01G65Z... | ULID format | Standard; regex: ^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$ |
Self-Hosted Troubleshooting: Railway/Kafka
See Self-Hosted Troubleshooting for the "events not metering" failure mode (Kafka volumes, topic provisioning, restart sequence) and sink-worker partition instability.
References
First-Party Documentation
SDKs
Related Skills
Reference
The full OpenAPI 3.0 spec is bundled at assets/openapi-spec.json. Use it as the source of truth for request/response schemas, query parameters, and error codes.