curl --request POST \
--url https://api.creem.io/v1/meters \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"name": "Image generations",
"event_name": "image.generated",
"aggregation": "sum",
"unit_label": "images",
"aggregation_property": "tokens"
}
'import requests
url = "https://api.creem.io/v1/meters"
payload = {
"name": "Image generations",
"event_name": "image.generated",
"aggregation": "sum",
"unit_label": "images",
"aggregation_property": "tokens"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Image generations',
event_name: 'image.generated',
aggregation: 'sum',
unit_label: 'images',
aggregation_property: 'tokens'
})
};
fetch('https://api.creem.io/v1/meters', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.creem.io/v1/meters",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Image generations',
'event_name' => 'image.generated',
'aggregation' => 'sum',
'unit_label' => 'images',
'aggregation_property' => 'tokens'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.creem.io/v1/meters"
payload := strings.NewReader("{\n \"name\": \"Image generations\",\n \"event_name\": \"image.generated\",\n \"aggregation\": \"sum\",\n \"unit_label\": \"images\",\n \"aggregation_property\": \"tokens\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.creem.io/v1/meters")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Image generations\",\n \"event_name\": \"image.generated\",\n \"aggregation\": \"sum\",\n \"unit_label\": \"images\",\n \"aggregation_property\": \"tokens\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.creem.io/v1/meters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Image generations\",\n \"event_name\": \"image.generated\",\n \"aggregation\": \"sum\",\n \"unit_label\": \"images\",\n \"aggregation_property\": \"tokens\"\n}"
response = http.request(request)
puts response.read_body{
"id": "mtr_abc123",
"store_id": "sto_abc123",
"name": "Image generations",
"event_name": "image.generated",
"aggregation": "sum",
"aggregation_property": "tokens",
"filter": {
"conjunction": "and",
"clauses": [
{
"property": "tier",
"operator": "equals",
"value": "pro"
}
]
},
"unit_label": "images",
"status": "active",
"created_at": "<string>",
"updated_at": "<string>"
}{
"error": {
"type": "invalid_request_error",
"code": "meter_name_taken",
"message": "A meter named \"Image generations\" already exists in this store",
"request_id": "req_abc123def456",
"param": "events[3].customer_id",
"details": {
"archived_holder": true,
"archived_holder_id": "mtr_abc123"
}
}
}{
"error": {
"type": "invalid_request_error",
"code": "meter_name_taken",
"message": "A meter named \"Image generations\" already exists in this store",
"request_id": "req_abc123def456",
"param": "events[3].customer_id",
"details": {
"archived_holder": true,
"archived_holder_id": "mtr_abc123"
}
}
}Create a meter
Define how a stream of usage events is aggregated into billable units. The unit label doubles as the display unit and as the credit bucket the meter settles into. A duplicate name within the store is rejected with 409 meter_name_taken.
curl --request POST \
--url https://api.creem.io/v1/meters \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"name": "Image generations",
"event_name": "image.generated",
"aggregation": "sum",
"unit_label": "images",
"aggregation_property": "tokens"
}
'import requests
url = "https://api.creem.io/v1/meters"
payload = {
"name": "Image generations",
"event_name": "image.generated",
"aggregation": "sum",
"unit_label": "images",
"aggregation_property": "tokens"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Image generations',
event_name: 'image.generated',
aggregation: 'sum',
unit_label: 'images',
aggregation_property: 'tokens'
})
};
fetch('https://api.creem.io/v1/meters', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.creem.io/v1/meters",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Image generations',
'event_name' => 'image.generated',
'aggregation' => 'sum',
'unit_label' => 'images',
'aggregation_property' => 'tokens'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.creem.io/v1/meters"
payload := strings.NewReader("{\n \"name\": \"Image generations\",\n \"event_name\": \"image.generated\",\n \"aggregation\": \"sum\",\n \"unit_label\": \"images\",\n \"aggregation_property\": \"tokens\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.creem.io/v1/meters")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Image generations\",\n \"event_name\": \"image.generated\",\n \"aggregation\": \"sum\",\n \"unit_label\": \"images\",\n \"aggregation_property\": \"tokens\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.creem.io/v1/meters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Image generations\",\n \"event_name\": \"image.generated\",\n \"aggregation\": \"sum\",\n \"unit_label\": \"images\",\n \"aggregation_property\": \"tokens\"\n}"
response = http.request(request)
puts response.read_body{
"id": "mtr_abc123",
"store_id": "sto_abc123",
"name": "Image generations",
"event_name": "image.generated",
"aggregation": "sum",
"aggregation_property": "tokens",
"filter": {
"conjunction": "and",
"clauses": [
{
"property": "tier",
"operator": "equals",
"value": "pro"
}
]
},
"unit_label": "images",
"status": "active",
"created_at": "<string>",
"updated_at": "<string>"
}{
"error": {
"type": "invalid_request_error",
"code": "meter_name_taken",
"message": "A meter named \"Image generations\" already exists in this store",
"request_id": "req_abc123def456",
"param": "events[3].customer_id",
"details": {
"archived_holder": true,
"archived_holder_id": "mtr_abc123"
}
}
}{
"error": {
"type": "invalid_request_error",
"code": "meter_name_taken",
"message": "A meter named \"Image generations\" already exists in this store",
"request_id": "req_abc123def456",
"param": "events[3].customer_id",
"details": {
"archived_holder": true,
"archived_holder_id": "mtr_abc123"
}
}
}Authorizations
API key for authentication. You can find your API key in the Creem dashboard under Settings > API Keys.
Body
Human-readable meter name, unique within your store
"Image generations"
The usage event name this meter consumes
"image.generated"
Aggregation applied to the matching events
count, sum, average, min, max, unique "sum"
Display unit for the metered quantity. Also names the customer-credits bucket the meter settles into.
"images"
Event property the aggregation reduces. Required for every aggregation except "count", which ignores it.
"tokens"
Optional filter narrowing which events the meter counts. Omitted means "count every event with this event name".
Show child attributes
Show child attributes
Response
Meter created
Meter ID
"mtr_abc123"
Store ID
"sto_abc123"
Meter name
"Image generations"
Usage event name the meter consumes
"image.generated"
Aggregation applied to matching events
count, sum, average, min, max, unique "sum"
Property the aggregation reduces; null for "count"
"tokens"
The meter filter; always present (empty clauses = match all)
Show child attributes
Show child attributes
Display unit
"images"
Whether the meter is active or archived
active, archived "active"
Creation timestamp (ISO 8601)
Last update timestamp (ISO 8601)