openapi: 3.0.3 info: title: OpenMeter API description: >- OpenMeter is open-source usage metering and billing for AI and API products. Ingest usage as CloudEvents, define meters that aggregate those events, query usage, manage subjects and customers, gate access with entitlements (metered, boolean, and static), features and grants, react to usage with notifications, and drive billing, plans, and subscriptions with Stripe integration. This is a faithful, representative subset of the real OpenMeter Cloud API (https://openmeter.cloud/api/v1) for API Evangelist catalog purposes; see the canonical spec at https://github.com/openmeterio/openmeter for the full surface. termsOfService: https://openmeter.io/terms contact: name: OpenMeter Support url: https://openmeter.io email: support@openmeter.io license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0 version: 1.0.0 servers: - url: https://openmeter.cloud description: OpenMeter Cloud - url: http://localhost:8888 description: Self-hosted (open source, default) security: - BearerAuth: [] tags: - name: Events description: Ingest usage events as CloudEvents and list ingested events. - name: Meters description: Define meters that aggregate events and query usage. - name: Subjects description: Subjects that usage is metered against. - name: Customers description: Customers used for entitlements, subscriptions, and billing. - name: Entitlements description: Metered, boolean, and static entitlements that gate access. - name: Features description: Features that entitlements are attached to. - name: Grants description: Usage grants that top up metered entitlement balances. - name: Notifications description: Notification channels, rules, and events for usage-driven alerts. - name: Billing description: Billing profiles, invoices, and customer overrides. - name: Plans description: Product catalog plans for subscriptions. paths: /api/v1/events: get: operationId: listEvents tags: - Events summary: List ingested events description: Lists ingested events with optional time and subject filters. parameters: - name: from in: query schema: type: string format: date-time - name: to in: query schema: type: string format: date-time - name: limit in: query schema: type: integer default: 100 responses: '200': description: List of ingested events. content: application/json: schema: type: array items: $ref: '#/components/schemas/IngestedEvent' '401': $ref: '#/components/responses/Unauthorized' post: operationId: ingestEvents tags: - Events summary: Ingest events description: >- Ingests an event or batch of events following the CloudEvents specification. Send a single CloudEvent as application/cloudevents+json or a batch as application/cloudevents-batch+json. requestBody: required: true content: application/cloudevents+json: schema: $ref: '#/components/schemas/CloudEvent' application/cloudevents-batch+json: schema: type: array items: $ref: '#/components/schemas/CloudEvent' responses: '204': description: Events accepted for ingestion. '400': description: Malformed CloudEvent. '401': $ref: '#/components/responses/Unauthorized' /api/v1/meters: get: operationId: listMeters tags: - Meters summary: List meters responses: '200': description: List of meters. content: application/json: schema: type: array items: $ref: '#/components/schemas/Meter' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createMeter tags: - Meters summary: Create meter requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Meter' responses: '201': description: Meter created. content: application/json: schema: $ref: '#/components/schemas/Meter' '401': $ref: '#/components/responses/Unauthorized' /api/v1/meters/{meterIdOrSlug}: parameters: - name: meterIdOrSlug in: path required: true schema: type: string get: operationId: getMeter tags: - Meters summary: Get meter responses: '200': description: A meter. content: application/json: schema: $ref: '#/components/schemas/Meter' '404': $ref: '#/components/responses/NotFound' delete: operationId: deleteMeter tags: - Meters summary: Delete meter responses: '204': description: Meter deleted. '404': $ref: '#/components/responses/NotFound' /api/v1/meters/{meterIdOrSlug}/query: get: operationId: queryMeter tags: - Meters summary: Query meter description: Queries usage for a meter, optionally grouped by subject and time window. parameters: - name: meterIdOrSlug in: path required: true schema: type: string - name: from in: query schema: type: string format: date-time - name: to in: query schema: type: string format: date-time - name: windowSize in: query schema: type: string enum: [MINUTE, HOUR, DAY] - name: subject in: query schema: type: array items: type: string - name: groupBy in: query schema: type: array items: type: string responses: '200': description: Meter query result. content: application/json: schema: $ref: '#/components/schemas/MeterQueryResult' '401': $ref: '#/components/responses/Unauthorized' /api/v1/meters/{meterIdOrSlug}/subjects: get: operationId: listMeterSubjects tags: - Meters summary: List meter subjects parameters: - name: meterIdOrSlug in: path required: true schema: type: string responses: '200': description: Subjects that have reported usage to the meter. content: application/json: schema: type: array items: type: string /api/v1/subjects: get: operationId: listSubjects tags: - Subjects summary: List subjects responses: '200': description: List of subjects. content: application/json: schema: type: array items: $ref: '#/components/schemas/Subject' post: operationId: upsertSubject tags: - Subjects summary: Upsert subjects requestBody: required: true content: application/json: schema: type: array items: $ref: '#/components/schemas/Subject' responses: '200': description: Subjects upserted. /api/v1/subjects/{subjectIdOrKey}: parameters: - name: subjectIdOrKey in: path required: true schema: type: string get: operationId: getSubject tags: - Subjects summary: Get subject responses: '200': description: A subject. content: application/json: schema: $ref: '#/components/schemas/Subject' delete: operationId: deleteSubject tags: - Subjects summary: Delete subject responses: '204': description: Subject deleted. /api/v1/customers: get: operationId: listCustomers tags: - Customers summary: List customers responses: '200': description: List of customers. content: application/json: schema: type: array items: $ref: '#/components/schemas/Customer' post: operationId: createCustomer tags: - Customers summary: Create customer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Customer' responses: '201': description: Customer created. content: application/json: schema: $ref: '#/components/schemas/Customer' /api/v1/features: get: operationId: listFeatures tags: - Features summary: List features responses: '200': description: List of features. content: application/json: schema: type: array items: $ref: '#/components/schemas/Feature' post: operationId: createFeature tags: - Features summary: Create feature requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Feature' responses: '201': description: Feature created. content: application/json: schema: $ref: '#/components/schemas/Feature' /api/v1/features/{featureId}: parameters: - name: featureId in: path required: true schema: type: string get: operationId: getFeature tags: - Features summary: Get feature responses: '200': description: A feature. content: application/json: schema: $ref: '#/components/schemas/Feature' delete: operationId: deleteFeature tags: - Features summary: Delete (archive) feature responses: '204': description: Feature archived. /api/v1/entitlements: get: operationId: listEntitlements tags: - Entitlements summary: List all entitlements responses: '200': description: List of entitlements. content: application/json: schema: type: array items: $ref: '#/components/schemas/Entitlement' /api/v1/entitlements/{entitlementId}: get: operationId: getEntitlementById tags: - Entitlements summary: Get entitlement by id parameters: - name: entitlementId in: path required: true schema: type: string responses: '200': description: An entitlement. content: application/json: schema: $ref: '#/components/schemas/Entitlement' /api/v1/subjects/{subjectIdOrKey}/entitlements: parameters: - name: subjectIdOrKey in: path required: true schema: type: string get: operationId: listSubjectEntitlements tags: - Entitlements summary: List subject entitlements responses: '200': description: The subject's entitlements. content: application/json: schema: type: array items: $ref: '#/components/schemas/Entitlement' post: operationId: createEntitlement tags: - Entitlements summary: Create a subject entitlement requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Entitlement' responses: '201': description: Entitlement created. content: application/json: schema: $ref: '#/components/schemas/Entitlement' /api/v1/subjects/{subjectIdOrKey}/entitlements/{entitlementIdOrFeatureKey}/value: get: operationId: getEntitlementValue tags: - Entitlements summary: Get entitlement value description: >- Returns whether the subject has access and, for metered entitlements, the current balance, usage, and overage. parameters: - name: subjectIdOrKey in: path required: true schema: type: string - name: entitlementIdOrFeatureKey in: path required: true schema: type: string responses: '200': description: The entitlement value / balance. content: application/json: schema: $ref: '#/components/schemas/EntitlementValue' /api/v1/subjects/{subjectIdOrKey}/entitlements/{entitlementIdOrFeatureKey}/grants: parameters: - name: subjectIdOrKey in: path required: true schema: type: string - name: entitlementIdOrFeatureKey in: path required: true schema: type: string get: operationId: listEntitlementGrants tags: - Grants summary: List subject entitlement grants responses: '200': description: Grants for the entitlement. content: application/json: schema: type: array items: $ref: '#/components/schemas/Grant' post: operationId: createGrant tags: - Grants summary: Create a grant on an entitlement requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Grant' responses: '201': description: Grant created. content: application/json: schema: $ref: '#/components/schemas/Grant' /api/v1/grants: get: operationId: listGrants tags: - Grants summary: List grants responses: '200': description: List of grants. content: application/json: schema: type: array items: $ref: '#/components/schemas/Grant' /api/v1/grants/{grantId}: delete: operationId: voidGrant tags: - Grants summary: Void grant parameters: - name: grantId in: path required: true schema: type: string responses: '204': description: Grant voided. /api/v1/notification/channels: get: operationId: listNotificationChannels tags: - Notifications summary: List notification channels responses: '200': description: List of notification channels. content: application/json: schema: type: array items: $ref: '#/components/schemas/NotificationChannel' post: operationId: createNotificationChannel tags: - Notifications summary: Create a notification channel requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NotificationChannel' responses: '201': description: Channel created. content: application/json: schema: $ref: '#/components/schemas/NotificationChannel' /api/v1/notification/rules: get: operationId: listNotificationRules tags: - Notifications summary: List notification rules responses: '200': description: List of notification rules. content: application/json: schema: type: array items: $ref: '#/components/schemas/NotificationRule' post: operationId: createNotificationRule tags: - Notifications summary: Create a notification rule requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NotificationRule' responses: '201': description: Rule created. content: application/json: schema: $ref: '#/components/schemas/NotificationRule' /api/v1/notification/events: get: operationId: listNotificationEvents tags: - Notifications summary: List notification events responses: '200': description: List of delivered notification events. content: application/json: schema: type: array items: $ref: '#/components/schemas/NotificationEvent' /api/v1/billing/invoices: get: operationId: listInvoices tags: - Billing summary: List invoices responses: '200': description: List of invoices. content: application/json: schema: type: array items: $ref: '#/components/schemas/Invoice' /api/v1/billing/profiles: get: operationId: listBillingProfiles tags: - Billing summary: List billing profiles responses: '200': description: List of billing profiles. content: application/json: schema: type: array items: $ref: '#/components/schemas/BillingProfile' /api/v1/plans: get: operationId: listPlans tags: - Plans summary: List plans responses: '200': description: List of plans. content: application/json: schema: type: array items: $ref: '#/components/schemas/Plan' post: operationId: createPlan tags: - Plans summary: Create plan requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Plan' responses: '201': description: Plan created. content: application/json: schema: $ref: '#/components/schemas/Plan' components: securitySchemes: BearerAuth: type: http scheme: bearer description: OpenMeter Cloud API token supplied as a Bearer token. responses: Unauthorized: description: Authentication is required or the token is invalid. content: application/json: schema: $ref: '#/components/schemas/Problem' NotFound: description: The requested resource was not found. content: application/json: schema: $ref: '#/components/schemas/Problem' schemas: CloudEvent: type: object description: A usage event following the CloudEvents 1.0 specification. required: - id - source - type - subject properties: id: type: string description: Unique identifier for the event (used for idempotent deduplication). example: 00001 source: type: string description: Identifies the context in which the event happened. example: my-app specversion: type: string default: '1.0' type: type: string description: The CloudEvent type, matched by meters via eventType. example: api-calls subject: type: string description: The subject (e.g. customer or user) the usage is metered against. example: customer-1 time: type: string format: date-time data: type: object description: Event payload; meter valueProperty and groupBy JSONPaths read from here. example: method: GET path: /v1/resource tokens: 1024 IngestedEvent: type: object properties: event: $ref: '#/components/schemas/CloudEvent' ingestedAt: type: string format: date-time validationError: type: string nullable: true Meter: type: object required: - slug - eventType - aggregation properties: id: type: string slug: type: string description: Unique, URL-friendly identifier for the meter. example: api_requests name: type: string description: type: string eventType: type: string description: The CloudEvent type this meter aggregates. example: api-calls aggregation: type: string enum: [SUM, COUNT, UNIQUE_COUNT, AVG, MIN, MAX] valueProperty: type: string description: JSONPath into event data for the metered value (not needed for COUNT). example: $.tokens groupBy: type: object additionalProperties: type: string description: Named JSONPath expressions to group usage by. example: method: $.method path: $.path MeterQueryResult: type: object properties: from: type: string format: date-time to: type: string format: date-time windowSize: type: string enum: [MINUTE, HOUR, DAY] data: type: array items: type: object properties: value: type: number windowStart: type: string format: date-time windowEnd: type: string format: date-time subject: type: string groupBy: type: object additionalProperties: type: string Subject: type: object required: - key properties: id: type: string key: type: string description: Unique subject key that events reference in their subject field. example: customer-1 displayName: type: string metadata: type: object additionalProperties: true stripeCustomerId: type: string nullable: true Customer: type: object required: - name properties: id: type: string key: type: string name: type: string currency: type: string example: USD usageAttribution: type: object properties: subjectKeys: type: array items: type: string Feature: type: object required: - key - name properties: id: type: string key: type: string example: api_requests name: type: string meterSlug: type: string description: Optional meter this feature draws usage from (for metered entitlements). example: api_requests metadata: type: object additionalProperties: true Entitlement: type: object required: - type - featureKey properties: id: type: string type: type: string enum: [metered, boolean, static] featureKey: type: string example: api_requests subjectKey: type: string example: customer-1 usagePeriod: type: object properties: interval: type: string enum: [DAY, WEEK, MONTH, YEAR] anchor: type: string format: date-time issueAfterReset: type: number description: Amount of usage granted at the start of each usage period. EntitlementValue: type: object properties: hasAccess: type: boolean balance: type: number usage: type: number overage: type: number Grant: type: object required: - amount properties: id: type: string amount: type: number description: Amount of usage to grant to the entitlement balance. priority: type: integer description: Lower priority grants are burned down first. default: 1 effectiveAt: type: string format: date-time expiration: type: object properties: duration: type: string enum: [HOUR, DAY, WEEK, MONTH, YEAR] count: type: integer recurrence: type: object properties: interval: type: string enum: [DAY, WEEK, MONTH, YEAR] anchor: type: string format: date-time NotificationChannel: type: object required: - type - name properties: id: type: string type: type: string enum: [WEBHOOK] name: type: string url: type: string format: uri description: Webhook URL that notification events are delivered to. signingSecret: type: string description: Secret used to sign webhook payloads (Svix-compatible). disabled: type: boolean default: false NotificationRule: type: object required: - type - name - channels properties: id: type: string type: type: string enum: [entitlements.balance.threshold] name: type: string channels: type: array items: type: string description: Channel ids that fire when the rule matches. thresholds: type: array items: type: object properties: value: type: number type: type: string enum: [PERCENT, NUMBER] features: type: array items: type: string NotificationEvent: type: object properties: id: type: string type: type: string createdAt: type: string format: date-time rule: $ref: '#/components/schemas/NotificationRule' deliveryStatus: type: array items: type: object properties: channelId: type: string state: type: string enum: [SUCCESS, FAILED, SENDING, PENDING] Invoice: type: object properties: id: type: string number: type: string customer: $ref: '#/components/schemas/Customer' status: type: string enum: [draft, issued, paid, void] currency: type: string total: type: string BillingProfile: type: object properties: id: type: string name: type: string default: type: boolean supplier: type: object additionalProperties: true workflow: type: object additionalProperties: true Plan: type: object required: - key - name properties: id: type: string key: type: string name: type: string currency: type: string example: USD phases: type: array items: type: object properties: key: type: string name: type: string rateCards: type: array items: type: object additionalProperties: true Problem: type: object description: RFC 7807 problem details. properties: type: type: string title: type: string status: type: integer detail: type: string