Metadata-Version: 2.3
Name: syvain-metrics-api-client
Version: 0.0.144
Summary: Typed Python client for the Syvain Metrics REST API
Requires-Dist: niquests>=3.16.0
Requires-Dist: pydantic>=2.13.3
Requires-Dist: typing-extensions>=4.15.0
Requires-Dist: pytest>=8.0.0 ; extra == 'dev'
Requires-Dist: ruff>=0.15.12 ; extra == 'dev'
Requires-Dist: ty>=0.0.34 ; extra == 'dev'
Requires-Python: >=3.10
Provides-Extra: dev
Description-Content-Type: text/markdown

# Syvain Metrics API Client

Typed Python client for the [Syvain Metrics](https://metrics.syvain.com/) REST
API.

This package maps directly onto the REST surface for experiments, folders,
metric query endpoints, annotations, and ingestion keys. If you only need to
record metrics from a training or evaluation job, use
`syvain-metrics-collector` instead.

## Install

```bash
uv add syvain-metrics-api-client
```

## Authentication

Use an explicit API key:

```python
from syvain_metrics_api_client import SyvainMetricsApiClient

client = SyvainMetricsApiClient("ak_org_...")
```

Use installed Syvain CLI auth:

```python
client = SyvainMetricsApiClient("local")
```

`local` reads `~/.config/syvain-metrics/auth.json`.

## Usage

```python
from syvain_metrics_api_client import SyvainMetricsApiClient

client = SyvainMetricsApiClient("local")

experiment = client.create_experiment(
    "mamba-run-001",
    description="Baseline mamba training run",
    metadata={"model": "mamba"},
).experiment

client.ingest_metrics(
    experiment.id,
    [
        {
            "client_event_id": "mamba-run-001/loss/1",
            "name": "loss",
            "value": 0.42,
            "step": 1,
            "metadata": {"split": "train"},
        }
    ],
)

series = client.query_metric_series(
    [
        {
            "experiment_id": experiment.id,
            "metric_name": "loss",
            "filter": {
                "metadata_key": "split",
                "metadata_value": "train",
            },
        }
    ],
    x_axis="step",
    limit=500,
)
catalog = client.query_metrics_catalog([experiment.id])
```

Every metric must include a stable `client_event_id`. Reuse the same value when
retrying the same event so ingestion can remain idempotent.

Metric metadata is validated against the series backend contract before a
request is sent: it must be a flat `str -> str` mapping with at most 32 keys,
128 UTF-8 bytes per key, 512 UTF-8 bytes per value, and 4096 UTF-8 bytes in its
canonical JSON representation.

Ingest and annotation creation calls mint and cache ingestion keys per
experiment. General API calls use the configured API key directly.

## Client Surface

Folders:

- `list_folders(...)`
- `create_folder(...)`
- `get_folder(...)`
- `patch_folder(...)`
- `rename_folder(...)`
- `move_folder(...)`

Experiments:

- `list_experiments(...)`
- `create_experiment(...)`
- `get_experiment(...)`
- `update_experiment_status(...)`
- `move_experiment(...)`

Metrics:

- `query_metric_series(...)`
- `query_metrics_catalog(...)`
- `ingest_metrics(...)`

Ingestion keys:

- `list_ingestion_keys(...)`
- `create_ingestion_key(...)`
- `revoke_ingestion_key(...)`
- `forget_ingestion_credential(...)`

Annotations:

- `list_annotations(...)`
- `create_annotation(...)`

Authentication:

- `auth_status()`

## Host and Timeouts

The client defaults to `https://metrics.syvain.com`.

```python
client = SyvainMetricsApiClient(
    "ak_org_...",
    host="https://metrics.syvain.com",
    timeout=10.0,
    ingest_timeout=60.0,
)
```

`timeout` applies to ordinary API calls. `ingest_timeout` applies to metric and
annotation ingestion calls.

## Write Retries and Idempotency

The client retries transient request failures for idempotent write operations.
For POST and PATCH requests it sends a generated `Idempotency-Key` header and
reuses that key across retry attempts for the same logical request.

Metric ingestion idempotency is controlled by each metric's `client_event_id`.
Use deterministic IDs derived from the run, metric name, step, and series
metadata when the same event may be retried by caller code.

## Errors

All package-specific failures inherit from `MetricsApiError`.

- `MetricsApiRequestError`: the API returned an HTTP error or could not be
  reached
- `MetricsApiResponseError`: the API returned a successful response that did
  not match the expected schema
- `MetricsApiAuthError`: local CLI auth was requested but unavailable or
  invalid
