Skip to content

Quickstart

This walkthrough reads back the run from the Ingestion API quickstart: it lists the project’s runs, finds the ones with a low final loss, and fetches the loss curve.

Terminal window
export METRANA_API_KEY="…" # portal user menu → Get API token
export METRANA_URL=$(printf '%s' "$METRANA_API_KEY" | tr '_-' '/+' | base64 -d | jq -r .url)
export ACCESS_TOKEN=$(curl -s -X POST "$METRANA_URL/api/management/v1/tokens/exchange" \
-H "Content-Type: application/json" \
-d "{\"api_token\": \"$METRANA_API_KEY\"}" | jq -r .access_token)
q() { # q <route> <json body>
curl -s -X POST "$METRANA_URL/api/query/v1/$1" \
-H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -d "$2"
}
Terminal window
q runs:list '{
"workspace": "my-workspace",
"project": "api-quickstart",
"attributePaths": ["config/optimizer", "sys/creation_time"],
"seriesSummaries": ["train/loss():last", "train/loss():min"],
"orderBy": "attr(sys/creation_time) DESC",
"limit": "20"
}'
{
"runs": [
{
"name": "run-001",
"experiment": "baseline",
"attributes": [
{"path": "config/optimizer", "stringValue": "adamw"},
{"path": "sys/creation_time", "timestampValue": "2026-09-30T09:00:00Z"}
],
"seriesSummaries": [
{"seriesSummary": "train/loss():last", "value": 1.21},
{"seriesSummary": "train/loss():min", "value": 1.21}
]
}
],
"totalCount": "1"
}

seriesSummaries computes a statistic of a series for every run — here the last and minimum loss. The strings are series summary selectors: a metric name, options in parentheses (none here), and functions after the colon.

Filters and orderings use the same selectors:

Terminal window
q runs:list '{
"workspace": "my-workspace",
"project": "api-quickstart",
"filter": "attr(config/optimizer) == \"adamw\" AND train/loss():last < 1.5",
"orderBy": "train/loss():min ASC"
}'

See Resource filters for every operator.

Terminal window
q float-series:list '{
"workspace": "my-workspace",
"project": "api-quickstart",
"runNames": ["run-001"],
"seriesQueries": ["train/loss()"],
"includeTimestamps": true
}'
{
"runPoints": [{
"run": "run-001",
"series": [{
"definition": {"regular": {"metricName": "train/loss", "scale": "ML_STEP"}},
"points": {
"steps": ["0", "1", "2", "3", "4"],
"values": [2.31, 1.87, 1.52, 1.34, 1.21],
"timestampMillis": ["1759233600000", "1759233600000", "1759233600000", "1759233600000", "1759233600000"]
}
}]
}]
}

Points come back columnar: steps[i], values[i] and timestampMillis[i] describe one point. For long series you would page with resumeToken, or ask for chart-ready buckets instead — see Reading series.

Terminal window
grpcurl -import-path libs/models/proto -proto query/v1/svc/api.proto \
-H "authorization: Bearer $ACCESS_TOKEN" \
-d '{"workspace": "my-workspace", "project": "api-quickstart", "seriesSummaries": ["train/loss():last"]}' \
"${METRANA_URL#https://}:443" metrana_protobuf.query.v1.svc.QueryService/ListRuns
import grpc
from metrana_protobuf.query.v1.svc import api_pb2, api_pb2_grpc
channel = grpc.secure_channel(
"app.metrana.ai:443",
grpc.ssl_channel_credentials(),
options=[("grpc.max_receive_message_length", 128 * 1024 * 1024)], # series pages can be large
)
stub = api_pb2_grpc.QueryServiceStub(channel)
response = stub.ListRuns(
api_pb2.ListRunsRequest(
workspace="my-workspace",
project="api-quickstart",
series_summaries=["train/loss():last"],
order_by="train/loss():last ASC",
),
metadata=(("authorization", f"Bearer {access_token}"),),
)
for run in response.runs:
print(run.name, [(s.series_summary, s.value) for s in run.series_summaries])