OpenMeter OSS quickstart

August 11, 2026 ยท View on GitHub

Run a complete local OpenMeter stack, send a usage event, and query its metered value.

Prerequisites

  • Docker with Compose
  • Git
  • one of:
    • Bash and curl
    • Node.js 22+ and npm for TypeScript
    • Python 3.9+ and pip for Python

1. Start OpenMeter

git clone https://github.com/openmeterio/openmeter.git
cd openmeter/quickstart
docker compose up -d --wait

The API is available at http://localhost:48888. The Compose stack also starts OpenMeter's workers and local Kafka, ClickHouse, PostgreSQL, Redis, and Svix dependencies.

Note

This setup uses latest OpenMeter images and development-grade dependencies. It is intended for local evaluation, not production.

2. Meter an event

The included configuration defines an api_requests_total meter that counts events with type request. Choose a client; each example sends one event and polls until its asynchronous processing completes.

Bash (curl)
curl -sS -o /dev/null -w '%{http_code}\n' \
  -X POST http://localhost:48888/api/v1/events \
  -H 'Content-Type: application/cloudevents+json' \
  --data-raw '{
    "specversion": "1.0",
    "type": "request",
    "id": "quickstart-curl-1",
    "source": "quickstart",
    "subject": "quickstart-curl",
    "data": { "method": "GET", "route": "/hello" }
  }'

response=
for attempt in 1 2 3 4 5 6 7 8 9 10; do
  response=$(curl -fsS 'http://localhost:48888/api/v1/meters/api_requests_total/query?subject=quickstart-curl')
  printf '%s' "$response" | grep -q '"value":1' && break
  sleep 1
done
printf '%s\n' "$response"

The ingest prints 204; the query response contains "subject":"quickstart-curl" and "value":1.

TypeScript SDK

Install the OpenMeter TypeScript SDK:

npm install @openmeter/sdk tsx

Save as quickstart.ts, then run npx tsx quickstart.ts:

import { OpenMeter } from '@openmeter/sdk'

const openmeter = new OpenMeter({ baseUrl: 'http://localhost:48888' })

const queryUsage = () =>
  openmeter.meters.query('api_requests_total', {
    subject: ['quickstart-typescript'],
  })

async function main() {
  await openmeter.events.ingest({
    type: 'request',
    id: 'quickstart-typescript-1',
    source: 'quickstart',
    subject: 'quickstart-typescript',
    data: { method: 'GET', route: '/hello' },
  })

  let usage = await queryUsage()
  for (let attempt = 1; usage.data[0]?.value !== 1 && attempt < 10; attempt++) {
    await new Promise((resolve) => setTimeout(resolve, 1000))
    usage = await queryUsage()
  }

  if (usage.data[0]?.value !== 1) {
    throw new Error('usage was not processed in time')
  }
  console.log(usage.data[0].value)
}

main().catch((error) => {
  console.error(error)
  process.exitCode = 1
})

The script prints 1.

Python SDK

The Python SDK is in preview, so install it with pre-releases enabled:

python -m pip install --pre openmeter

Save as quickstart.py, then run python quickstart.py:

import time

from openmeter import Client
from openmeter.models import Event

with Client(endpoint="http://localhost:48888") as openmeter:
    openmeter.events.ingest_event(
        Event(
            id="quickstart-python-1",
            source="quickstart",
            specversion="1.0",
            type="request",
            subject="quickstart-python",
            data={"method": "GET", "route": "/hello"},
        )
    )

    for _ in range(10):
        usage = openmeter.meters.query_json(
            "api_requests_total",
            subject=["quickstart-python"],
        )
        if usage.data and usage.data[0].value == 1:
            break
        time.sleep(1)
    else:
        raise RuntimeError("usage was not processed in time")

    print(usage.data[0].value)

The script prints 1.0.

3. Explore

Group usage by hour, method, and route:

curl 'http://localhost:48888/api/v1/meters/api_requests_total/query?windowSize=HOUR&groupBy=method&groupBy=route'

Then continue with:

Cleanup

Remove the quickstart containers and their data volumes:

docker compose down -v