Getting Started
Base URL, versioning, authentication, rate limits, and response conventions for the Klipfolio public API.
The Klipfolio public API lets you create and manage PowerMetrics assets, including metrics, goals, tags, dashboards, and data connections programmatically — the same assets you'd otherwise build by hand in the PowerMetrics UI. Every request is authenticated and rate-limited per API key.
Status: public beta (
1.0-beta). Shapes may change before GA.
Field-level shape (names, types, enums, required and read-only status) for Metrics, Goals, Tags, Dashboards, Direct connections, Data feed connections, and Data feeds is generated from the OpenAPI 3.1 document and is authoritative there — see the API Reference tab, or fetch the live document directly at GET https://api-public.klipfolio.com/v1.0-beta/openapi.json (an API key is required, same as any other request — see Authentication below). These guides are authoritative for everything else: base URL/versioning, authentication, rate limiting, response conventions, which endpoints to call in what order to create each kind of asset, and endpoints without an OpenAPI schema (Query builder, Events/webhooks, and read-only/action sub-endpoints such as /data_feeds/generate and /metrics/:metricId/query). Examples in these guides are illustrative — they show the shape and field names you should expect, not values captured verbatim from a live response.
Base URL & versioning
https://api-public.klipfolio.com/<version>/<resource>
A request's leading path segment selects the API version. For the public API the beta marker is required:
| Request path | Result |
|---|---|
/v1.0-beta/... | ✅ served (canonical beta) |
/v1-beta/... | ✅ served (alias) |
/... (no segment) | ✅ served — defaults to 1.0-beta |
/v1/... | ❌ 400 — beta marker required |
/v1.0/..., /v1.5/... | ❌ 400 — specific subversions rejected |
All accepted versions route to the same v1 controller.
Authentication
Every request must present a Klipfolio v2 API key as a bearer token:
Authorization: Bearer kf_live_<keyid>.<secret>.<checksum>
Issue keys from your Klipfolio account under My Profile → API Keys. (If your account also shows a legacy API Key (Klips Only) field, that's a different system — it won't work here.)
- Scopes:
GET/HEADrequire the key'sapi:readscope; all other methods requireapi:write. A scope mismatch returns403. - A malformed key, an unknown key, or a wrong secret all return a bare
401(the API does not reveal which check failed). - If the key service is unreachable, the API fails closed (
503).
Rate limiting
Each request is throttled per API key. Responses carry the draft-7 RateLimit / RateLimit-Policy headers. A throttled request receives:
HTTP/1.1 429 Too Many Requests
Retry-After: <seconds>
{ "status": 429, "message": "Too Many Requests" }
Default limits for the standard tier are 60 requests/minute and 10,000/day (both enforced). Limits are set per tier by Klipfolio, not encoded in the key — your limits can change without needing to reissue a key.
Conventions
Error responses use a consistent shape:
{
"errorId": "required.openapi.validation",
"status": 400,
"message": "Bad Request",
"meta": {}
}errorId is the part to branch on: message is the bare status text for most errors, since an upstream message can describe internals. The exception is a read-only conflict, which returns its own message naming the fields that cannot be changed — that message is the point of rejecting rather than ignoring.
Common statuses: 400 validation error (missing or invalid fields), 401 auth failure, 403 scope mismatch, 404 not found, 429 rate limited, 503 upstream unavailable.
An update checks the resource exists before it checks the body, so a write to something that isn't there answers 404 even when the body is also invalid.
Create envelope. POST create endpoints for metrics, goals, tags, direct connections, generated data feeds, and event subscriptions return 201 with a meta/data envelope:
{
"meta": { "url": "/metrics/abc123" },
"data": { "id": "abc123", "...": "..." }
}The one exception: a POST /events/subscriptions request that fans out into more than one subscription (mixing datafeed.source.* with other events) has no single resource for meta.url to name, so that case returns a bare array instead — see the Events guide.
GET, PUT, and list endpoints return the resource (or an array of resources) directly, without the envelope, unless noted otherwise in a resource's own guide.
Deletes return 204 No Content with an empty body.
Field conventions:
- Read-only fields (ids,
createdAt,updatedAt, status, etc.) are returned in responses but never writable. Sending one back is not an error as long as it still matches the stored value, so a resource fetched withGETcan be edited and sent straight back withPUT— there is no need to strip these fields first. Sending one with a different value is rejected with400, naming the fields and both values, rather than being quietly discarded. On create, where there is nothing to compare against, a read-only field is always ignored. - Server-maintained fields are never compared, so a value that went stale between your
GETand yourPUTis not an error:createdAt,updatedAt,dataUpdatedAt,timeRangeStart,timeRangeEnd,status,last_refresh_outcome,last_successful_refresh_timestampandsource.date_last_refresh. They change on their own — a metric that refreshes between your two calls movesstatusanddataUpdatedAtwith no action from you. A data feed'sjoined_to_idsis read-only but is compared: it describes the data model, not refresh state. Which category each field of each asset falls into is listed in Field Reference. - Dates are ISO 8601 strings (e.g.
2026-05-28T23:59:59.999Z) in responses. - Enums (e.g.
status,positiveDirection, columntype) are surfaced in UPPER CASE publicly. - A
versionfield may accompany a resource; if you send it on write it must match the resource's mapper version ("1.0"). - Required fields must be present on every write,
PUTincluded — aPUTreplaces rather than merges, so a required field you leave out is missing, not inherited. Which fields those are is listed per asset in Field Reference;nameon a metric, tag or goal is the common case. - Extra/unknown fields in a write body are rejected with
400.
Where to go next
See the API Reference tab, or these two one-page overviews: the API Endpoint Index for every endpoint, and the Field Reference for every field of every asset with its editable/read-only status. If you're trying to create an asset, start at Creating a Metric — it routes you to the right workflow guide depending on where your data lives.
Updated 6 days ago