Getting Started
Your First Query
Query bucketed usage for a meter.
Usage queries return buckets. A bucket is a time window with a meter aggregation applied.
Configure A Client
Use an API key from the dashboard. Configure the client once, then reuse it for usage queries.
BASE_URL="http://localhost:18081"
OPEN_SPANNER_API_KEY="osp_..."import (
"os"
httptransport "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/ssubedir/open-spanner/sdk/go/client"
"github.com/ssubedir/open-spanner/sdk/go/client/usages"
"github.com/ssubedir/open-spanner/sdk/go/models"
)
// Configure once at service startup.
transport := httptransport.New("localhost:18081", client.DefaultBasePath, []string{"http"})
transport.DefaultAuthentication = httptransport.BearerToken(os.Getenv("OPEN_SPANNER_API_KEY"))
api := client.New(transport, strfmt.Default)import { client, searchUsageBuckets } from "@ssubedir/open-spanner";
// Configure once at service startup.
client.setConfig({
baseUrl: process.env.OPEN_SPANNER_BASE_URL ?? "http://localhost:18081",
headers: {
Authorization: `Bearer ${process.env.OPEN_SPANNER_API_KEY}`,
},
});import os
from open_spanner_client import AuthenticatedClient
from open_spanner_client.api.usages import search_usage_buckets
from open_spanner_client.models.internal_metering_adapters_http_usage_search_request import (
InternalMeteringAdaptersHttpUsageSearchRequest,
)
# Configure once at service startup.
client = AuthenticatedClient(
base_url=os.environ.get("OPEN_SPANNER_BASE_URL", "http://localhost:18081"),
token=os.environ["OPEN_SPANNER_API_KEY"],
raise_on_unexpected_status=True,
)using Microsoft.Kiota.Abstractions.Authentication;
using Microsoft.Kiota.Http.HttpClientLibrary;
using OpenSpanner;
using OpenSpanner.Models;
// Configure once at service startup.
var authProvider = new BaseBearerTokenAuthenticationProvider(
new ApiKeyProvider(Environment.GetEnvironmentVariable("OPEN_SPANNER_API_KEY")!)
);
var adapter = new HttpClientRequestAdapter(authProvider)
{
BaseUrl = Environment.GetEnvironmentVariable("OPEN_SPANNER_BASE_URL") ?? "http://localhost:18081",
};
var client = new OpenSpannerClient(adapter);
sealed class ApiKeyProvider(string apiKey) : IAccessTokenProvider
{
public AllowedHostsValidator AllowedHostsValidator { get; } = new();
public Task<string> GetAuthorizationTokenAsync(
Uri uri,
Dictionary<string, object>? additionalAuthenticationContext = null,
CancellationToken cancellationToken = default)
{
return Task.FromResult(apiKey);
}
}Query Usage
This query returns daily api_requests usage for one subject:
curl "$BASE_URL/v1/usages?subject=org_123&meter=api_requests&from=2026-06-01T00:00:00Z&to=2026-06-10T00:00:00Z&bucket_size=day" \
-H "Authorization: Bearer $OPEN_SPANNER_API_KEY"buckets, err := api.Usages.SearchUsageBuckets(
usages.NewSearchUsageBucketsParams().WithRequest(&models.InternalMeteringAdaptersHTTPUsageSearchRequest{
Subject: "org_123",
Meter: "api_requests",
From: "2026-06-01T00:00:00Z",
To: "2026-06-10T00:00:00Z",
BucketSize: "day",
Limit: 100,
}),
)
if err != nil {
panic(err)
}
for _, bucket := range buckets.Payload {
fmt.Println(bucket.BucketStart, bucket.Quantity)
}const { data: buckets } = await searchUsageBuckets({
body: {
subject: "org_123",
meter: "api_requests",
from: "2026-06-01T00:00:00Z",
to: "2026-06-10T00:00:00Z",
bucket_size: "day",
limit: 100,
},
throwOnError: true,
});
for (const bucket of buckets ?? []) {
console.log(bucket.bucket_start, bucket.quantity);
}buckets = search_usage_buckets.sync(
client=client,
body=InternalMeteringAdaptersHttpUsageSearchRequest(
subject="org_123",
meter="api_requests",
from_="2026-06-01T00:00:00Z",
to="2026-06-10T00:00:00Z",
bucket_size="day",
limit=100,
),
)
for bucket in buckets or []:
print(bucket.bucket_start, bucket.quantity)var buckets = await client.V1.Usages.Search.PostAsync(new SearchRequest
{
Subject = "org_123",
Meter = "api_requests",
From = "2026-06-01T00:00:00Z",
To = "2026-06-10T00:00:00Z",
BucketSize = "day",
Limit = 100,
});
if (buckets is not null)
{
foreach (var bucket in buckets)
{
Console.WriteLine($"{bucket.BucketStart} {bucket.Quantity}");
}
}Use group_by=subject when you want one bucket row per subject in the same response. For richer filters or grouping, use POST /v1/usages/search or the dashboard usage page.