Getting started with the VerOps Public API
The VerOps Public API at api.verops.io: what it is, the /v1 base URL and versioning, creating an API-scoped key, the X-Api-Key header, your first curl call, rate limits, the JSON error model, timestamp formats, retries and idempotency, and the synchronous no-webhooks model.
What the VerOps Public API is
The VerOps Public API is a stable, versioned HTTP API for programmatic access to your VerOps organization. Everything you can see in the product is scoped to your organization, and so is the API: a key only ever reads and writes your own organization's data. With it you can:
- Send custom data in — your own metrics and events, stored alongside the rest of your telemetry.
- Query that custom data back — raw samples, time-bucketed aggregates, or event searches.
- Read your platform data out — metric names and values, logs, alerts, and software inventory — as JSON your scripts and integrations can consume.
Base URL and versioning
The API is served at:
https://api.verops.io
Every endpoint lives under the /v1 prefix, for example https://api.verops.io/v1/metrics/names. The /v1 segment is the API version. We add fields to responses without changing the version, but any breaking change ships under a new prefix (such as /v2) so your existing integrations keep working. No endpoints are deprecated today.
Get an API key with the API scope
Requests authenticate with an API key. Keys are created by an administrator under Settings -> API Keys. When you create the key, enable the API scope — that is the scope that grants Public API access.
A key looks like ta_live_xxxxxxxxxxxxxxxxxxxxxxxx. Copy it when it is shown; treat it like a password and store it in a secret manager, never in source control.
Warning: There are two scopes. API grants Public API access. Ingest is a separate scope used by agents to push telemetry and does not grant Public API access. A key that only has Ingest will be rejected with 403 forbidden. Make sure the API scope is enabled.
Send the key on every request
Pass the key in the X-Api-Key header, or as a Bearer token in the Authorization header — either is accepted:
# Preferred: X-Api-Key header
curl https://api.verops.io/v1/metrics/names \
-H "X-Api-Key: ta_live_xxxxxxxxxxxxxxxxxxxxxxxx"
# Equivalent: Authorization: Bearer
curl https://api.verops.io/v1/metrics/names \
-H "Authorization: Bearer ta_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Your first call
The health check needs no key and is the quickest way to confirm you can reach the API:
curl https://api.verops.io/v1/health
# -> 200 {"status":"ok"}
Now make an authenticated call. This lists the metric names available to your organization:
export KEY=ta_live_xxxxxxxxxxxxxxxxxxxxxxxx
curl https://api.verops.io/v1/metrics/names \
-H "X-Api-Key: $KEY"
# -> 200 {"data":["http_server_request_count","cpu_usage", ...]}
A 200 with a {"data": ...} body means your key works and has the API scope. A 401 means the key is missing or invalid; a 403 means the key is valid but lacks the API scope.
Timestamps
Every timestamp field in the API — ts, start, end, startTime, endTime — accepts either form, and you can mix them freely:
- an epoch value in milliseconds as a number, for example
1700000000000; - an ISO-8601 string, for example
"2023-11-14T22:13:20Z".
All results are returned in UTC. Timestamps in responses (the ts field on points and events) are always epoch milliseconds as integers.
Rate limits
Each key has a per-minute request limit — a generous default, or a custom value set when the key is created. If you exceed it, the API returns 429 with a Retry-After header giving the number of seconds to wait. Back off for that long and retry.
The error model
Any non-2xx response returns a JSON envelope with a machine-readable code and a human-readable message:
{
"error": {
"code": "bad_request",
"message": "metricName is required"
}
}
| Code | Status | Meaning |
|---|---|---|
bad_request |
400 | The request body or parameters are invalid. |
unauthorized |
401 | The API key is missing or invalid. |
forbidden |
403 | The key is valid but does not have the API scope. |
not_found |
404 | The resource does not exist (for example an unknown alert id). |
rate_limited |
429 | Per-minute rate limit exceeded. Includes a Retry-After header. |
internal_error |
500 | An unexpected error on our side. Safe to retry with backoff. |
unavailable |
503 | The service is temporarily unavailable. Safe to retry with backoff. |
Retries and idempotency
Read endpoints (every GET, and the query endpoints) are safe to retry freely. The send endpoints (POST /v1/custom/metrics and POST /v1/custom/events) are append-only and not idempotent — if a call succeeds on the server but the response is lost to a network error, retrying may record the sample or event a second time. For most metrics and events that duplication is harmless, but design with it in mind.
Recommended retry policy:
- Retry on
429(after waitingRetry-Afterseconds) and on500/503, using exponential backoff. - Do not retry on
400,401, or403— those will fail again until you fix the request or the key.
No webhooks or callbacks
The API is entirely synchronous request and response. There are no webhooks, no async callbacks, and no long-polling. To learn about new data you poll the read endpoints on your own schedule.
Interactive reference
Two machine-readable specifications and an interactive explorer are available:
| Resource | URL |
|---|---|
| Interactive reference (custom-data endpoints) | https://api.verops.io/v1/docs |
| OpenAPI spec (custom-data endpoints) | https://api.verops.io/v1/openapi.json |
| OpenAPI spec (platform-read endpoints) | https://api.verops.io/openapi.json |
Tip: Set your key once as an environment variable (export KEY=ta_live_...) and reference it as$KEYin every example on this page, so you never paste a secret into a command you might share.