- Overview
- Authentication
- Errors and limits
- Code examples
- Moving from Classic
- KPIs
- KPI Categories
- KPI Categories / KPIs
- Breakdown Items
- KPI Entries
- KPI Frequencies
- KPI Icons
- KPI Units
- Reports
- Users
SimpleKPI AI › API reference
KPIs
A KPI is a single measure your account tracks — its name, how often data is entered against it, which direction counts as good, and how values roll up over a period. These endpoints cover the full lifecycle.
To work with the KPIs inside one category, use KPI Categories / KPIs instead.
Base URL https://api.simplekpi.com/v1
Endpoints
- List KPIs —
GET /v1/kpis - Create a KPI —
POST /v1/kpis - Get a KPI —
GET /v1/kpis/{id} - Update a KPI —
PUT /v1/kpis/{id} - Delete a KPI —
DELETE /v1/kpis/{id}
KPI object
| Name | Type | Read Only | Mandatory | Max Len. | Notes |
|---|---|---|---|---|---|
id | integer | yes | no | Assigned by SimpleKPI when the KPI is created. | |
category_id | integer | no | no | The category the KPI belongs to. | |
icon_id | integer (16 bit) | no | no | The icon shown against the KPI. Although the contract does not mark it mandatory, the value is checked — omitting it sends 0, which is not a real icon, and the request fails with 400. Read the ids from KPI Icons. | |
unit_id | integer | no | no | How the KPI's values are formatted. Checked against your account for the same reason as icon_id, so send a real id from KPI Units rather than leaving it out. | |
frequency_id | string | no | yes | How often data is entered against the KPI. Case sensitive, and must be one of the ids returned by KPI Frequencies. D Daily, W Weekly, M Monthly, Q Quarterly, Y Yearly. | |
name | string | no | yes | 100 | What the KPI is called. |
description | string | no | no | 150 | Nullable. Free text shown alongside the KPI. |
target_default | decimal | no | no | Nullable. The target applied to new entries when none is given. | |
value_direction | string | no | yes | Which way the KPI has to move to be doing well. Case sensitive. U Up is good, D Down is good, N Neither. | |
aggregate_function | string | no | yes | How the KPI's values roll up across a period. Case sensitive. SUM Add the values together, AVG Average the values. | |
is_calculated | boolean | yes | no | True when the KPI is derived from other KPIs. Calculated KPIs are maintained in the app and their entries cannot be written through the API. | |
sort_order | integer (16 bit) | no | no | Position of the KPI within its category. | |
is_active | boolean | no | no | Inactive KPIs stay on the account but are hidden from day-to-day views. | |
created_at | datetime | yes | no | ||
updated_at | datetime | yes | no |
List KPIs
GET /v1/kpis
Returns a plain JSON array. There is no wrapper object and no total count — page until you get a short page.
Requires kpis:read on the API key.
Parameters
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
page | integer | no | 1 | Which page to return, counting from 1. |
rows | integer | no | 500 | How many rows per page. Defaults to 500. |
Using curl
curl https://api.simplekpi.com/v1/kpis \ -H "Authorization: Bearer skpi_your_api_key"
Example response
Status: 200 OK
[
{
"id": 1234,
"category_id": 5478,
"icon_id": 1,
"unit_id": 123,
"frequency_id": "W",
"name": "New Sales",
"description": "Closed-won deals per week",
"target_default": 100,
"value_direction": "U",
"aggregate_function": "SUM",
"is_calculated": false,
"sort_order": 1,
"is_active": true,
"created_at": "2026-02-21T10:57:00",
"updated_at": "2026-02-21T10:58:00"
}
]Status codes
| Code | Meaning |
|---|---|
200 | OK |
400 | Bad Request |
401 | Unauthorized |
403 | Forbidden |
429 | Too Many Requests |
Create a KPI
POST /v1/kpis
Returns the KPI as stored, including the id it was given.
Requires kpis:write on the API key.
Using curl
curl https://api.simplekpi.com/v1/kpis \
-X POST \
-H "Authorization: Bearer skpi_your_api_key" \
-H "Content-Type: application/json" \
-d '{"category_id":5478,"icon_id":1,"unit_id":123,"frequency_id":"W","name":"New Sales","description":"Closed-won deals per week","target_default":100,"value_direction":"U","aggregate_function":"SUM","sort_order":1,"is_active":true}'Example request body
{
"category_id": 5478,
"icon_id": 1,
"unit_id": 123,
"frequency_id": "W",
"name": "New Sales",
"description": "Closed-won deals per week",
"target_default": 100,
"value_direction": "U",
"aggregate_function": "SUM",
"sort_order": 1,
"is_active": true
}Example response
Status: 201 Created
{
"id": 1234,
"category_id": 5478,
"icon_id": 1,
"unit_id": 123,
"frequency_id": "W",
"name": "New Sales",
"description": "Closed-won deals per week",
"target_default": 100,
"value_direction": "U",
"aggregate_function": "SUM",
"is_calculated": false,
"sort_order": 1,
"is_active": true,
"created_at": "2026-02-21T10:57:00",
"updated_at": "2026-02-21T10:58:00"
}Status codes
| Code | Meaning |
|---|---|
201 | Created |
400 | Bad Request |
401 | Unauthorized |
403 | Forbidden |
429 | Too Many Requests |
Get a KPI
GET /v1/kpis/{id}
Requires kpis:read on the API key.
Parameters
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | yes | The KPI to return. |
Using curl
curl https://api.simplekpi.com/v1/kpis/{id} \
-H "Authorization: Bearer skpi_your_api_key"Example response
Status: 200 OK
{
"id": 1234,
"category_id": 5478,
"icon_id": 1,
"unit_id": 123,
"frequency_id": "W",
"name": "New Sales",
"description": "Closed-won deals per week",
"target_default": 100,
"value_direction": "U",
"aggregate_function": "SUM",
"is_calculated": false,
"sort_order": 1,
"is_active": true,
"created_at": "2026-02-21T10:57:00",
"updated_at": "2026-02-21T10:58:00"
}Status codes
| Code | Meaning |
|---|---|
200 | OK |
401 | Unauthorized |
403 | Forbidden |
404 | Not Found |
429 | Too Many Requests |
Update a KPI
PUT /v1/kpis/{id}
A full replacement, not a patch: anything you leave out is reset to its default rather than kept.
Requires kpis:write on the API key.
Parameters
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | yes | The KPI to replace. |
Using curl
curl https://api.simplekpi.com/v1/kpis/{id} \
-X PUT \
-H "Authorization: Bearer skpi_your_api_key" \
-H "Content-Type: application/json" \
-d '{"category_id":5478,"icon_id":1,"unit_id":123,"frequency_id":"W","name":"New Sales","description":"Closed-won deals per week","target_default":100,"value_direction":"U","aggregate_function":"SUM","sort_order":1,"is_active":true}'Example request body
{
"category_id": 5478,
"icon_id": 1,
"unit_id": 123,
"frequency_id": "W",
"name": "New Sales",
"description": "Closed-won deals per week",
"target_default": 100,
"value_direction": "U",
"aggregate_function": "SUM",
"sort_order": 1,
"is_active": true
}Example response
Status: 200 OK
{
"id": 1234,
"category_id": 5478,
"icon_id": 1,
"unit_id": 123,
"frequency_id": "W",
"name": "New Sales",
"description": "Closed-won deals per week",
"target_default": 100,
"value_direction": "U",
"aggregate_function": "SUM",
"is_calculated": false,
"sort_order": 1,
"is_active": true,
"created_at": "2026-02-21T10:57:00",
"updated_at": "2026-02-21T10:58:00"
}Status codes
| Code | Meaning |
|---|---|
200 | OK |
400 | Bad Request |
401 | Unauthorized |
403 | Forbidden |
404 | Not Found |
429 | Too Many Requests |
Delete a KPI
DELETE /v1/kpis/{id}
Deletes the KPI and every entry recorded against it. This cannot be undone.
Requires kpis:write on the API key.
Parameters
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | yes | The KPI to delete. |
Using curl
curl https://api.simplekpi.com/v1/kpis/{id} \
-X DELETE \
-H "Authorization: Bearer skpi_your_api_key"Status codes
| Code | Meaning |
|---|---|
204 | No Content |
400 | Bad Request |
401 | Unauthorized |
403 | Forbidden |
404 | Not Found |
429 | Too Many Requests |