🎉 Announcing our $3 million seed round
Logo
Getting Started

Webhooks

Only available in OpenMeter Cloud
Sign Up

OpenMeter webhooks enable you to report aggregated usage to external systems like billing and CRMs to keep your data in sync. Webhooks can run every minute, hour, or day and be filtered by both subject and usage.

Configuring Webhooks

OpenMeter Cloud has a UI to configure webhooks.

Setting up a webhook via API that reports the daily usage looks as:

curl -X POST https://openmeter.cloud/api/v1/reports \
  -H 'Content-Type: application/cloudevents+json' \
  -H 'Authorization: Bearer <API_TOKEN>' \
  --data-raw '
{
  "slug": "my_usage_report",
  "meterIdOrSlug": "ai_prompt_tokens",
  "type": "webhook",
  "schedule": {
    "interval": "1d",
    "startAt": "2023-01-01T00:00:00.000Z"
  },
  "query": {
    "groupBy": ["model"]
  },
  "endpoint": {
    "url": "https://mydomain/api/webhooks"
  },
  "filter": {
    "usage": {
      "$gt": 100
    }
  }
}'

Note how we use the optional filter property here only to report usage greater than 100.

Filtering is possible on both subject and usage. Available filters are: $gt, $gte, $lt, $lte, $eq, $ne, $in and $nin. You can filter for specific subjects as filter: { subject: { $in: ["customer-1", "customer-2"] } }.

Example Webhook Payload

Webhooks are delivered as JSON payloads to your webhook endpoint. We deliver a separate webhook for each subject. The usage array contains the aggregated usage for the subject. If the report defines a group by the usage property, it will contain a separate entry for each group.

{
  "report": {
    "slug": "my_usage_report"
  },
  "usage": [
    {
      "subject": "customer-1",
      "value": 500,
      "groupBy": {
        "model": "gpt-4"
      },
      "windowStart": "2023-01-01T00:00:00Z",
      "windowEnd": "2023-01-02T00:00:00Z"
    },
    {
      "subject": "customer-1",
      "value": 10000,
      "groupBy": {
        "model": "gpt-3-turbo"
      },
      "windowStart": "2023-01-01T00:00:00Z",
      "windowEnd": "2023-01-02T00:00:00Z"
    }
  ],
  "query": {
    "from": "2023-01-01T00:00:00Z",
    "to": "2023-01-02T00:00:00Z",
    "subject": "customer-1",
    "groupBy": ["model"]
  },
  "meter": {
    "id": "01H98E5HHJ8K0AYXQKM3EKAVYG",
    "slug": "ai_prompt_tokens",
    "description": "OpenAI Prompt Tokens",
    "aggregation": "SUM",
    "windowSize": "MINUTE",
    "eventType": "tokens",
    "valueProperty": "$.prompt_tokens",
    "groupBy": {
      "model": "$.model"
    }
  }
}

Consuming Webhooks

To deliver and verify webhooks we use the Svix webhook service. You can read more about veryfing payloads. Let's see the following Next.js example that verifies the webhook signature and logs the payload.

import { Webhook } from 'svix';
 
const wh = new Webhook(process.env.WEBHOOK_SECRET);
 
export default async function handler(req, res) {
  if (req.method !== 'POST') {
    res.status(405).json({});
    return;
  }
 
  const payload = (await buffer(req)).toString();
 
  try {
    // Verify the webhook signature
    msg = wh.verify(payload, req.headers);
  } catch (err) {
    res.status(400).json({ message: 'Bad signature' });
    return;
  }
 
  // Webhook payload with reported usage
  if (msg.type === 'report.meter') {
    console.log(msg);
    res.json({});
  }
 
  res.status(400).json({ message: 'Unknown event type' });
  return;
}

OpenMeter Cloud also gives you visibility into webhook delivery and errors.

Last edited on April 18, 2024