API reference
The metrics ingest endpoint accepts one or many metric data points via a single POST request. Authenticated by a workspace API key.
Balcony exposes one public endpoint for programmatic metric ingestion. It accepts individual data points or batches of up to 100 points in a single request.
Authentication
All requests require a workspace API key passed as a Bearer token:
Authorization: Bearer <your-api-key>
API keys are workspace-scoped and can be created in your workspace settings. A key that is invalid, expired, or belongs to a different workspace returns a 401.
Ingest metric data points
POST /api/v1/metrics
Accepts a single metric data point or an array of up to 100 points.
Request body
Single point:
{
"metric_id": "3f2d1b8a-...",
"value": 94.2,
"timestamp": "2025-11-01T09:00:00Z",
"origin": "monitoring-pipeline-v2"
}
Batch (array):
[
{
"metric_id": "3f2d1b8a-...",
"value": 94.2,
"timestamp": "2025-11-01T09:00:00Z"
},
{
"metric_id": "7c4e9f0d-...",
"value": 12
}
]
Fields
| Field | Type | Required | Description |
|---|---|---|---|
metric_id | string (UUID) | Yes | The ID of the target metric. Must belong to a mechanism in the authenticated workspace. |
value | number | Yes | A finite numeric value. |
timestamp | string (ISO 8601) | No | The time the value was recorded. Defaults to the time of ingestion if omitted. |
origin | string | No | A label identifying the data source — useful for tracing where a value came from. |
How to find a metric ID
Metric IDs are available in the mechanism editor. Open a mechanism, navigate to the Metrics section, and copy the ID from the metric's detail view.
Limits
- Maximum 100 points per request.
- All
metric_idvalues in a request must belong to the authenticated workspace. A single invalid or inaccessible ID in a batch causes the entire request to fail with a404.
Success response
{ "ingested": 3 }
Returns a 200 with the count of successfully ingested points.
Error responses
401 — Missing or invalid API key
{ "error": "Missing API key" }
{ "error": "Invalid or expired API key" }
400 — Validation failure
{
"error": "Validation failed",
"details": [
"[1] metric_id is required",
"[2] value must be a finite number"
]
}
400 — Batch too large
{ "error": "Maximum 100 points per request" }
404 — Unknown metric IDs
{
"error": "One or more metric IDs not found or not accessible",
"invalid": ["7c4e9f0d-..."]
}
500 — Server error
{ "error": "Failed to insert metric points" }
Example: curl
curl -X POST https://balcony.academy/api/v1/metrics \
-H "Authorization: Bearer bky_..." \
-H "Content-Type: application/json" \
-d '[
{
"metric_id": "3f2d1b8a-0000-0000-0000-000000000001",
"value": 94.2,
"timestamp": "2025-11-01T09:00:00Z",
"origin": "risk-scoring-pipeline"
}
]'
Example: JavaScript
const response = await fetch('/api/v1/metrics', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify([
{
metric_id: '3f2d1b8a-0000-0000-0000-000000000001',
value: 94.2,
timestamp: new Date().toISOString(),
origin: 'risk-scoring-pipeline',
},
]),
});
const result = await response.json();
// { ingested: 1 }