Submit Response
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
organization_id: '<string>',
campaign_id: '<string>',
facility_id: '<string>',
values: {},
attachment_file_ids: {}
})
};
fetch('https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/responses', 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}/responses"
payload = {
"organization_id": "<string>",
"campaign_id": "<string>",
"facility_id": "<string>",
"values": {},
"attachment_file_ids": {}
}
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}/responses \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"organization_id": "<string>",
"campaign_id": "<string>",
"facility_id": "<string>",
"values": {},
"attachment_file_ids": {}
}
'{
"response_set_id": "<string>",
"campaign_assignment_id": "<string>",
"submitted_at": "<string>",
"values": {},
"attachments": {}
}Submit Response
Submit KPI values and optional evidence attachments from the authenticated in-app flow
POST
/
v1
/
custom-kpi-datasets
/
{dataset_id}
/
responses
Submit Response
const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'x-organization-id': '<x-organization-id>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
organization_id: '<string>',
campaign_id: '<string>',
facility_id: '<string>',
values: {},
attachment_file_ids: {}
})
};
fetch('https://api.dcycle.io/v1/custom-kpi-datasets/{dataset_id}/responses', 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}/responses"
payload = {
"organization_id": "<string>",
"campaign_id": "<string>",
"facility_id": "<string>",
"values": {},
"attachment_file_ids": {}
}
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}/responses \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>' \
--data '
{
"organization_id": "<string>",
"campaign_id": "<string>",
"facility_id": "<string>",
"values": {},
"attachment_file_ids": {}
}
'{
"response_set_id": "<string>",
"campaign_assignment_id": "<string>",
"submitted_at": "<string>",
"values": {},
"attachments": {}
}← Custom KPI
Submit a Custom KPI response with values and optional evidence attachments. This is the authenticated submission flow — the caller must be a logged-in member of the organization.
Submissions from external data owners arrive through the magic-link portal, which posts to an
internal endpoint authenticated with Dcycle’s own webhook key — it is not callable with an
organization API key, so it is not documented here.
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 dataset
Body Parameters
string
required
UUID of the organization this response belongs toRetrieve available options from
GET /v2/organizations/treestring
required
UUID of the campaign being responded to
string
UUID of the facility (optional — used to match an assignment)Retrieve available options from
GET /v1/facilitiesarray[object]
required
KPI values to submit (1–100 entries, no duplicate
kpi_id). Each entry:| Field | Type | Description |
|---|---|---|
kpi_id | string | UUID of the KPI definition |
value_numeric | number | For number/percentage types (nullable) |
value_text | string | For text type, max 10 000 chars (nullable) |
value_date | string | For date type, ISO date (nullable) |
option_id | string | For select type — UUID of the chosen option (nullable) |
array[string]
UUIDs of evidence files previously uploaded via Presigned URL. Max 20 files.
Response
Returns the created response set with saved values and attachment metadata (HTTP 201).string
Response set UUID
string
Resolved campaign-assignment UUID
string
ISO 8601 timestamp
array[object]
Saved value objects
array[object]
Attachment metadata:
| Field | Type | Description |
|---|---|---|
file_id | string | File UUID |
file_name | string | Original file name |
file_url | string | Presigned download URL |
Example
curl -X POST "https://api.dcycle.io/v1/custom-kpi-datasets/${DATASET_ID}/responses" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}" \
-H "Content-Type: application/json" \
-d '{
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"campaign_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"values": [
{"kpi_id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "value_numeric": 42.5},
{"kpi_id": "d4e5f6a7-b8c9-0123-defa-234567890123", "value_text": "Completed audit"}
],
"attachment_file_ids": ["e5f6a7b8-c9d0-1234-efab-345678901234"]
}'
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}/responses",
headers=headers,
json={
"organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"campaign_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"values": [
{"kpi_id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "value_numeric": 42.5},
],
},
)
result = response.json()
print(f"Response set: {result['response_set_id']}, {len(result['values'])} values saved")
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}/responses`, {
organization_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
campaign_id: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
values: [
{ kpi_id: 'c3d4e5f6-a7b8-9012-cdef-123456789012', value_numeric: 42.5 },
],
}, { headers })
.then(response => {
console.log(`Response set: ${response.data.response_set_id}`);
console.log(`Values saved: ${response.data.values.length}`);
});
Successful Response
{
"response_set_id": "f1a2b3c4-d5e6-7890-abcd-ef9876543210",
"campaign_assignment_id": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"submitted_at": "2025-06-20T14:30:00Z",
"values": [
{
"id": "e1f2a3b4-c5d6-7890-abcd-ef1234567890",
"assignment_id": "d4e5f6a7-b8c9-0123-defa-234567890123",
"response_set_id": "f1a2b3c4-d5e6-7890-abcd-ef9876543210",
"kpi_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"value_numeric": 42.5,
"value_text": null,
"value_date": null,
"option_id": null,
"submitted_at": "2025-06-20T14:30:00Z",
"submitter_email": "admin@company.com",
"submitter_user_id": "b9f1e2d3-0000-0000-0000-000000000001",
"created_at": "2025-06-20T14:30:00Z"
}
],
"attachments": [
{
"file_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"file_name": "energy-audit-2025.pdf",
"file_url": "https://storage.dcycle.io/..."
}
]
}
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: Duplicatekpi_id entries in the values array
{
"detail": [
{
"loc": ["body", "values"],
"msg": "Duplicate kpi_id entries are not allowed in a single submission",
"type": "value_error"
}
]
}
Related Endpoints
Presigned URL
Upload evidence files before submitting
Dataset Values
View all submitted values across campaigns
Was this page helpful?