- 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
Errors and limits
Every failure from the SimpleKPI AI API comes back in the same shape, so a client only has to learn one. Successful responses are covered on theresource pages.
The error object
Errors are RFC 7807 problem details, served as application/problem+json rather thanapplication/json. Check the content type before parsing a failure as if it were the resource you asked for.
| Name | Type | Read Only | Mandatory | Max Len. | Notes |
|---|---|---|---|---|---|
type | string | yes | no | Nullable. A URI identifying the kind of problem. | |
title | string | yes | no | Nullable. A short summary of the problem, the same for every occurrence of this type. | |
status | integer | yes | no | Nullable. The HTTP status code, repeated in the body. | |
detail | string | yes | no | Nullable. What went wrong with this particular request. | |
instance | string | yes | no | Nullable. The path that produced the error. |
Status: 404 Not Found
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404,
"detail": "No KPI with id 9999 on this account.",
"instance": "/v1/kpis/9999"
}Validation errors
A 400 caused by the contents of your request carries an extraerrors object, keyed by field name. That is the part worth showing someone — it says which field was wrong and why.
| Name | Type | Read Only | Mandatory | Max Len. | Notes |
|---|---|---|---|---|---|
type | string | yes | no | Nullable. A URI identifying the kind of problem. | |
title | string | yes | no | Nullable. A short summary, usually "One or more validation errors occurred." | |
status | integer | yes | no | Nullable. The HTTP status code, repeated in the body. | |
detail | string | yes | no | Nullable. What went wrong, when there is more to say than the field errors below. | |
instance | string | yes | no | Nullable. The path that produced the error. | |
errors | object | yes | no | Field name to the list of things wrong with it, e.g. {"aggregate_function": ["The aggregate function is case sensitive and can only be AVG or SUM."]}. This is the part worth showing a user. |
Status: 400 Bad Request
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"aggregate_function": [
"The aggregate function is case sensitive and can only be AVG or SUM."
],
"value_direction": [
"The value direction is case sensitive and can only be U(p), D(own) or N(one)."
]
}
}Status codes
| Code | Meaning |
|---|---|
200 | The request succeeded. |
201 | A new resource was created. The body is the resource as stored. |
204 | The request succeeded and there is no body. Returned by every delete. |
400 | The request was malformed, or a value failed validation. See above. |
401 | The API key was missing, malformed, unknown, expired or revoked. |
403 | The key is valid but lacks the scope this endpoint needs. |
404 | No such resource on your account. Also returned when a resource exists but sits under a different parent than the one in the path. |
409 | The request conflicts with the current state — a duplicate name, or a resource still in use. |
429 | You are sending too fast. See below. |
Two success cases are worth singling out, because the status code alone does not tell you what happened:
- Writing a single KPI entry returns
201for a new entry and200for an update. If the entry resolved but had nothing to store,200comes back with astored: falseobject instead. See KPI Entries. - A batch write returns
200even when every row was rejected. Readrows_addedandrows_rejectedrather than trusting the status.
Paging
List endpoints take page and rows. pagecounts from 1 and rows defaults to 500.
https://api.simplekpi.com/v1/kpientries?kpiId=1234&rows=100&page=2
Responses are plain arrays, so there is no total to read. Keep requesting pages until one comes back with fewer than rows items.
Rate limits
Two limits apply, and a request has to satisfy both. Going over either returns429 with a Retry-After header saying how long to wait.
| Limit | Requests | Applies to |
|---|---|---|
| Per client | 300 / 60s | Every request, including ones that fail to authenticate. |
| Per API key | 600 / 60s | Sustained throughput, so one busy integration cannot starve another. |
Honour Retry-After rather than retrying immediately, and back off rather than looping. If you are hitting the limit on a bulk load, the fix is usually the batch endpoint — a few hundred entries in one request instead of a few hundred requests.
These limits are generous by design and may be raised. Treat them as the floor your integration should cope with, not a number to tune against.