List Workforce Trainings Paginated
const options = {
method: 'GET',
headers: {'x-api-key': '<x-api-key>', 'x-organization-id': '<x-organization-id>'}
};
fetch('https://api.dcycle.io/v1/own_workforce_trainings/paginated', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/own_workforce_trainings/paginated"
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>"
}
response = requests.get(url, headers=headers)
print(response.text)curl --request GET \
--url https://api.dcycle.io/v1/own_workforce_trainings/paginated \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>'{
"items": {},
"total": 123,
"page": 123,
"size": 123,
"filter_hash": "<string>"
}List Workforce Trainings Paginated
Retrieve training records in pages, with filters, group view and a filter hash
GET
/
v1
/
own_workforce_trainings
/
paginated
List Workforce Trainings Paginated
const options = {
method: 'GET',
headers: {'x-api-key': '<x-api-key>', 'x-organization-id': '<x-organization-id>'}
};
fetch('https://api.dcycle.io/v1/own_workforce_trainings/paginated', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.dcycle.io/v1/own_workforce_trainings/paginated"
headers = {
"x-api-key": "<x-api-key>",
"x-organization-id": "<x-organization-id>"
}
response = requests.get(url, headers=headers)
print(response.text)curl --request GET \
--url https://api.dcycle.io/v1/own_workforce_trainings/paginated \
--header 'x-api-key: <x-api-key>' \
--header 'x-organization-id: <x-organization-id>'{
"items": {},
"total": 123,
"page": 123,
"size": 123,
"filter_hash": "<string>"
}← Own Workforce API
The paginated training list, and the one to build against. It takes the same filters as the flat list, adds group view and column filters, and returns the
filter_hash that Bulk Delete Workforce Trainings by Filters requires.
This endpoint declares no response schema in the OpenAPI document, so generated clients will see an untyped body. The shape below is what it actually returns; the items are the same training objects as List Workforce Trainings.
Request
Headers
string
required
Your API key for authenticationExample:
sk_live_1234567890abcdefstring
required
Your organization UUIDExample:
a8315ef3-dd50-43f8-b7ce-d839e68d51faQuery Parameters
integer
default:"1"
Page number, starting at 1
integer
default:"50"
Page size, between 1 and 100
array[string]
Filter by source upload file. The nil UUID matches rows with no file.
datetime
Only rows created at or after this instant
datetime
Only rows created on or before this instant, inclusive
string
Free-text search, up to 255 characters
boolean
default:"false"
Group view.
true widens the list to the header organization’s accepted business family.array[string]
Restrict a group-view list to these organizations. Only meaningful with
consolidate_group=true.string
Scope to a project’s reporting perimeter, together with
scope_to_project_organizationsboolean
default:"false"
Narrow the perimeter to the organizations attached to
project_idResponse
array[object]
Training records — see List Workforce Trainings for the fields
integer
Rows matching the filters across all pages
integer
Current page
integer
Current page size
string
Fingerprint of the applied filters, required by bulk delete by filters
Example
curl -X GET "https://api.dcycle.io/v1/own_workforce_trainings/paginated?page=1&size=50" \
-H "x-api-key: ${DCYCLE_API_KEY}" \
-H "x-organization-id: ${DCYCLE_ORG_ID}"
import os
import requests
headers = {
"x-api-key": os.getenv("DCYCLE_API_KEY"),
"x-organization-id": os.getenv("DCYCLE_ORG_ID"),
}
page = 1
total_hours = 0.0
while True:
response = requests.get(
"https://api.dcycle.io/v1/own_workforce_trainings/paginated",
headers=headers,
params={"page": page, "size": 100},
).json()
total_hours += sum(record["hours"] for record in response["items"])
if page * response["size"] >= response["total"]:
break
page += 1
print(f"{total_hours} training hours")
const axios = require('axios');
const headers = {
'x-api-key': process.env.DCYCLE_API_KEY,
'x-organization-id': process.env.DCYCLE_ORG_ID
};
axios.get('https://api.dcycle.io/v1/own_workforce_trainings/paginated', {
headers,
params: { page: 1, size: 50 }
})
.then(({ data }) => {
console.log(`${data.total} trainings, page ${data.page} of ${Math.ceil(data.total / data.size)}`);
})
.catch(error => console.error(error));
Successful Response
{
"items": [
{
"id": "3d9b0a11-2c4e-4f6a-8b1d-5e7f9a0c2d4e",
"own_workforce_id": "550e8400-e29b-41d4-a716-446655440000",
"external_employee_id": "EMP-2024-001",
"type": "Health and safety",
"description": "Annual fire safety refresher",
"hours": 4.0,
"start_date": "2026-03-02",
"end_date": "2026-03-02",
"file_id": "aa11bb22-cc33-4d44-8e55-ff6677889900",
"file_name": "trainings_2026.csv",
"status": "active",
"custom_values": {}
}
],
"total": 320,
"page": 1,
"size": 50,
"filter_hash": "4e8a1c07d3b95f26"
}
Common Errors
401 Unauthorized
Cause: the key is invalid, or it does not belong to the organization inx-organization-id — the two are looked up as a pair. A request carrying no credentials at all answers AUTH_REQUIRED instead.
{
"detail": "Invalid API key for organization",
"code": "INVALID_API_KEY"
}
403 Forbidden
Cause: the key’s owner is not an enabled member of the organization inx-organization-id.
{
"detail": "Logged User is not Member of Organization",
"code": "LOGGED_USER_NOT_MEMBER"
}
422 Unprocessable Entity
Cause: a malformed parameter, orsize above 100.
{
"detail": [
{
"type": "less_than_equal",
"loc": ["query", "size"],
"msg": "Input should be less than or equal to 100"
}
]
}
Related Endpoints
Trainings unique values
Build the file filter
Bulk delete by filters
Delete exactly what this returned
Was this page helpful?