Code examples and SDKs

The same core operations (send a metric, query it back, read alerts) shown in cURL, Python (requests), and JavaScript (fetch), plus a retry helper. There is no official SDK yet, but the OpenAPI specs at /v1/openapi.json and /openapi.json generate one with openapi-generator.

public-apiexamplescurlpythonjavascriptsdkopenapiopenapi-generatorretry

Three core operations, three languages

The same three operations — send a metric, query it back, and read platform alerts — shown in cURL, Python, and JavaScript. In every example the API key comes from an environment variable named VEROPS_API_KEY; never hard-code a key.

cURL

export VEROPS_API_KEY=ta_live_xxxxxxxxxxxxxxxxxxxxxxxx
BASE=https://api.verops.io

# 1. Send a metric
curl -X POST "$BASE/v1/custom/metrics" \
  -H "X-Api-Key: $VEROPS_API_KEY" -H "Content-Type: application/json" \
  -d '{"metrics":[{"name":"orders.count","value":42,"labels":{"region":"us"}}]}'

# 2. Query it back (hourly sum)
curl -X POST "$BASE/v1/custom/metrics/query" \
  -H "X-Api-Key: $VEROPS_API_KEY" -H "Content-Type: application/json" \
  -d '{"metricName":"orders.count","start":1700000000000,
       "end":1700604800000,"step":"1h","agg":"sum"}'

# 3. Read active alerts
curl "$BASE/v1/alerts?status=active&page=0&size=20" \
  -H "X-Api-Key: $VEROPS_API_KEY" 

Python (requests)

import os
import requests

BASE = "https://api.verops.io"
KEY = os.environ["VEROPS_API_KEY"]
session = requests.Session()
session.headers.update({"X-Api-Key": KEY})


def send_metric(name, value, labels=None):
    body = {"metrics": [{"name": name, "value": value, "labels": labels or {}}]}
    r = session.post(f"{BASE}/v1/custom/metrics", json=body, timeout=30)
    r.raise_for_status()          # 202 on success
    return r.json()["accepted"]


def query_metric(name, start_ms, end_ms, step="1h", agg="sum"):
    body = {"metricName": name, "start": start_ms, "end": end_ms,
            "step": step, "agg": agg}
    r = session.post(f"{BASE}/v1/custom/metrics/query", json=body, timeout=30)
    r.raise_for_status()
    return r.json()["points"]


def active_alerts(page=0, size=20):
    r = session.get(f"{BASE}/v1/alerts",
                    params={"status": "active", "page": page, "size": size},
                    timeout=30)
    r.raise_for_status()
    return r.json()["data"]          # list of alerts; paging is in ["meta"]


if __name__ == "__main__":
    print("accepted:", send_metric("orders.count", 42, {"region": "us"}))
    print("points:", query_metric("orders.count", 1700000000000, 1700604800000))
    print("alerts:", active_alerts())

A small helper that respects Retry-After and backs off on 429 and 5xx:

import time

def post_with_retry(session, url, body, max_attempts=5):
    for attempt in range(1, max_attempts + 1):
        r = session.post(url, json=body, timeout=30)
        if r.status_code < 300:
            return r.json()
        if r.status_code == 429 or r.status_code >= 500:
            wait = int(r.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue
        r.raise_for_status()      # 4xx other than 429: do not retry
    raise RuntimeError("exhausted retries")

JavaScript (Node fetch)

Uses the built-in fetch available in modern Node and browsers.

const BASE = "https://api.verops.io";
const KEY = process.env.VEROPS_API_KEY;
const headers = { "X-Api-Key": KEY, "Content-Type": "application/json" };

async function sendMetric(name, value, labels = {}) {
  const res = await fetch(`${BASE}/v1/custom/metrics`, {
    method: "POST",
    headers,
    body: JSON.stringify({ metrics: [{ name, value, labels }] }),
  });
  if (!res.ok) throw new Error(`send failed: ${res.status}`);
  return (await res.json()).accepted;   // 202
}

async function queryMetric(name, startMs, endMs, step = "1h", agg = "sum") {
  const res = await fetch(`${BASE}/v1/custom/metrics/query`, {
    method: "POST",
    headers,
    body: JSON.stringify({ metricName: name, start: startMs, end: endMs, step, agg }),
  });
  if (!res.ok) throw new Error(`query failed: ${res.status}`);
  return (await res.json()).points;
}

async function activeAlerts(page = 0, size = 20) {
  const url = `${BASE}/v1/alerts?status=active&page=${page}&size=${size}`;
  const res = await fetch(url, { headers: { "X-Api-Key": KEY } });
  if (!res.ok) throw new Error(`alerts failed: ${res.status}`);
  return (await res.json()).data;   // array of alerts; paging is in .meta
}

(async () => {
  console.log("accepted:", await sendMetric("orders.count", 42, { region: "us" }));
  console.log("points:", await queryMetric("orders.count", 1700000000000, 1700604800000));
  console.log("alerts:", await activeAlerts());
})();

Is there an official SDK?

There is no official SDK yet. Because the API ships machine-readable OpenAPI specifications, you can generate a typed client in most languages today. Two specs are published:

Spec Covers
https://api.verops.io/v1/openapi.json The custom-data endpoints (send and query).
https://api.verops.io/openapi.json The platform-read endpoints (metrics, logs, alerts, inventory).

Generate a client with openapi-generator:

# Python client from the custom-data spec
openapi-generator-cli generate \
  -i https://api.verops.io/v1/openapi.json \
  -g python -o ./verops-client-python

# TypeScript client from the platform-read spec
openapi-generator-cli generate \
  -i https://api.verops.io/openapi.json \
  -g typescript-fetch -o ./verops-client-ts

The interactive reference at https://api.verops.io/v1/docs lets you try the custom-data endpoints from the browser.

Best practice: Whatever language you use, centralize three things in one client wrapper: the base URL, the API key from an environment variable or secret manager, and the retry policy (honor Retry-After, back off on 429 and 5xx, never retry 400 / 401 / 403). Every call then inherits correct, consistent behavior.