Ingest a MetricBatch — the same payload the ZAP transport carries
Writes every sample in a luxfi/metric `MetricBatch` into the calling org's store and answers `{written}`: the number of SAMPLES stored, not families and…
POST /v1/metrics/batch
| Address | https://api.hanzo.ai/v1/metrics/batch |
| Method | POST |
| Operation | post_metrics_batch |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Writes every sample in a luxfi/metric MetricBatch into the calling org's store and answers {written}: the number of SAMPLES stored, not families and not metrics. This is the exact wire shape the ZAP MsgMetricBatch transport carries, so the HTTP door and the optional ZAP push receiver share one code path and one meaning — the transport is an optimisation, never a different contract.
A counter or gauge lands as one sample. A histogram or summary contributes DERIVED <name>_sum and <name>_count series, so one metric can write more than one sample and written can exceed the number of metrics you sent. The batch's own TimestampNs stamps every sample it carries.
The tenant is the gateway-minted X-Org-Id header, falling back to the deployment brand and then default; each org gets its own store, WAL-durable under the deployment's data dir. A body that does not decode is 400.
Request
The document declares no body for POST /v1/metrics/batch. The handler is typed in cloud but its shape is not yet emitted, so the fields are not listed here — ask the MCP door's describe for post_metrics_batch, which answers from the running route.
Response
The document declares no response body for this operation. It answers 200 on success and the platform error shape on failure — see Errors.
Examples
hanzo metrics batchimport { Configuration, MetricsApi } from 'hanzoai';
const api = new MetricsApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postMetricsBatch();from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import MetricsApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = MetricsApi(client).post_metrics_batch()cfg := cloud.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := cloud.NewAPIClient(cfg)
resp, _, err := client.MetricsAPI.PostMetricsBatch(context.Background()).Execute()
if err != nil {
return err
}use hanzo_cloud::apis::{configuration::Configuration, metrics_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = metrics_api::post_metrics_batch(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.MetricsApi;
ApiClient client = new ApiClient();
client.setRequestInterceptor(b -> b.header("Authorization", "Bearer " + System.getenv("HANZO_API_KEY")));
var result = new MetricsApi(client).postMetricsBatch();curl -X POST https://api.hanzo.ai/v1/metrics/batch \
-H "Authorization: Bearer $HANZO_API_KEY"The door reaches metrics through the metrics tool, which names its 11 operations with its own verbs — this one among them, under a name only the door declares. describe explains any of them:
curl -X POST https://api.hanzo.ai/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "describe",
"arguments": {
"op": "get_log_health"
}
}
}'How is this guide?