Create KPI
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
description: '<string>',
unit: '<string>',
value_type: '<string>',
required: true,
sort_order: 123,
options: {}
})
};
fetch('https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/kpis', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/kpis"
payload = {
"name": "<string>",
"description": "<string>",
"unit": "<string>",
"value_type": "<string>",
"required": True,
"sort_order": 123,
"options": {}
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/kpis \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"name": "<string>",
"description": "<string>",
"unit": "<string>",
"value_type": "<string>",
"required": true,
"sort_order": 123,
"options": {}
}
'{
"id": "<string>",
"dataset_id": "<string>",
"name": "<string>",
"description": {},
"unit": {},
"value_type": "<string>",
"required": true,
"sort_order": 123,
"options": {},
"created_at": {},
"updated_at": {}
}Create KPI
Add a new KPI definition to an existing dataset
POST
/
v1
/
custom-kpi-datasets
/
{dataset_id}
/
kpis
Create KPI
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
description: '<string>',
unit: '<string>',
value_type: '<string>',
required: true,
sort_order: 123,
options: {}
})
};
fetch('https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/kpis', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/kpis"
payload = {
"name": "<string>",
"description": "<string>",
"unit": "<string>",
"value_type": "<string>",
"required": True,
"sort_order": 123,
"options": {}
}
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)curl --request POST \
--url https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/kpis \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"name": "<string>",
"description": "<string>",
"unit": "<string>",
"value_type": "<string>",
"required": true,
"sort_order": 123,
"options": {}
}
'{
"id": "<string>",
"dataset_id": "<string>",
"name": "<string>",
"description": {},
"unit": {},
"value_type": "<string>",
"required": true,
"sort_order": 123,
"options": {},
"created_at": {},
"updated_at": {}
}← Custom KPI
Add a new KPI (question) definition to a dataset. Each KPI defines what data owners will be asked during campaigns.
Cause: Options provided for a non-select type
Request
Headers
string
required
Your API key for authenticationExample:
sk_live_1234567890abcdefstring
required
Your organization UUIDExample:
a8315ef3-dd50-43f8-b7ce-d839e68d51faPath Parameters
string
required
UUID of the parent datasetExample:
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"Body Parameters
string
required
KPI name (1–255 characters)Example:
"Monthly electricity consumption"string
KPI description (max 2000 characters)Example:
"Total kWh consumed from all sources"string
Measurement unit (max 50 characters)Example:
"kWh", "m³", "tonnes"string
default:"number"
Expected answer type. One of:
number, text, percentage, date, boolean, selectboolean
default:"true"
Whether a response value is mandatory
integer
default:"0"
Display order within the dataset (0-based)
array[object]
Required for
Options are forbidden for non-select types.
select type. List of selectable options (2–100). Each object has:| Field | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Option label (1–255 chars, unique per KPI case-insensitive) |
sort_order | integer | No | Display order (default 0) |
Response
Returns the created KPI definition (HTTP 201).string
KPI UUID.
string
Parent dataset UUID.
string
KPI display name.
string | null
KPI description.
string | null
Measurement unit (e.g.
m³, kWh).string
Data type:
number, text, percentage, date, boolean, or select.boolean
Whether a response value is mandatory.
integer
Display order within the dataset.
array[object]
Available choices for
select-type KPIs. Each has id, label, and sort_order.datetime
Timestamp when the KPI was created
datetime | null
Timestamp when the KPI was last updated
Example
curl -X POST "https://api.dcycle.io/v1/custom-kpi-datasets/${DATASET_ID}/kpis" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Content-Type: application/json" \
-d '{
"name": "Monthly electricity consumption",
"unit": "kWh",
"value_type": "number",
"required": true,
"sort_order": 0
}'
import requests
import os
headers = {
"x-api-key": os.getenv("DCYCLE_API_KEY"),
"x-organization-id": os.getenv("DCYCLE_ORG_ID"),
"Content-Type": "application/json",
}
dataset_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
response = requests.post(
f"https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/kpis",
headers=headers,
json={
"name": "Monthly electricity consumption",
"unit": "kWh",
"value_type": "number",
"required": True,
"sort_order": 0,
},
)
kpi = response.json()
print(f"Created KPI: {kpi['id']} ({kpi['value_type']})")
const axios = require('axios');
const headers = {
'x-api-key': process.env.DCYCLE_API_KEY,
'x-organization-id': process.env.DCYCLE_ORG_ID,
'Content-Type': 'application/json',
};
const datasetId = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';
axios.post(`https://api.dcycle.io/v1/custom-kpi-datasets/${datasetId}/kpis`, {
name: 'Monthly electricity consumption',
unit: 'kWh',
value_type: 'number',
required: true,
sort_order: 0,
}, { headers })
.then(response => console.log(`Created KPI: ${response.data.id}`));
Successful Response
{
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"dataset_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Monthly electricity consumption",
"description": null,
"unit": "kWh",
"value_type": "number",
"required": true,
"sort_order": 0,
"options": [],
"created_at": "2025-03-10T14:00:00Z",
"updated_at": null
}
Select Type Example
curl -X POST "https://api.dcycle.io/v1/custom-kpi-datasets/${DATASET_ID}/kpis" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Content-Type: application/json" \
-d '{
"name": "Primary energy source",
"value_type": "select",
"options": [
{"label": "Grid electricity", "sort_order": 0},
{"label": "Solar PV", "sort_order": 1},
{"label": "Natural gas", "sort_order": 2},
{"label": "Other", "sort_order": 3}
]
}'
Common Errors
401 Unauthorized
Cause: Missing or invalid API key{"detail": "Invalid API key for organization", "code": "INVALID_API_KEY"}
403 Forbidden
Cause: The authenticated user is not a member of the organization{"detail": "Logged User is not Member of Organization", "code": "LOGGED_USER_NOT_MEMBER"}
422 Validation Error
Cause: Select KPI missing options{
"detail": [
{
"loc": ["body", "__root__"],
"msg": "A select KPI must define options.",
"type": "value_error"
}
]
}
{
"detail": [
{
"loc": ["body", "__root__"],
"msg": "Only select-type KPIs can define options.",
"type": "value_error"
}
]
}
404 Not Found
Cause: Dataset not found{
"detail": "Dataset not found"
}
Related Endpoints
Update KPI
Modify a KPI definition
Delete KPI
Remove a KPI from the dataset
Was this page helpful?