curl --request POST \
--url https://{subdomain}.conveyour.com/api/compliance \
--header 'Content-Type: application/json' \
--header 'x-conveyour-token: <api-key>' \
--data '
{
"group_id": "<string>",
"contact_query": {},
"content_query.lesson_tags.all": [
"<string>"
],
"content_query.lesson_tags.any": [
"<string>"
],
"content_query.completed_after": "<string>",
"content_query.released_only": true,
"content_query.released_after": "<string>",
"submission_query.enabled": true,
"submission_query.completed_statuses": [
"<string>"
],
"submission_query.submission_collection_ids": [
"<string>"
],
"callback_url": "<string>",
"include_lessons": true,
"include_submissions": true
}
'const options = {
method: 'POST',
headers: {'x-conveyour-token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
group_id: '<string>',
contact_query: {},
'content_query.lesson_tags.all': ['<string>'],
'content_query.lesson_tags.any': ['<string>'],
'content_query.completed_after': '<string>',
'content_query.released_only': true,
'content_query.released_after': '<string>',
'submission_query.enabled': true,
'submission_query.completed_statuses': ['<string>'],
'submission_query.submission_collection_ids': ['<string>'],
callback_url: '<string>',
include_lessons: true,
include_submissions: true
})
};
fetch('https://{subdomain}.conveyour.com/api/compliance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const options = {
method: 'POST',
headers: {'x-conveyour-token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
group_id: '<string>',
contact_query: {},
'content_query.lesson_tags.all': ['<string>'],
'content_query.lesson_tags.any': ['<string>'],
'content_query.completed_after': '<string>',
'content_query.released_only': true,
'content_query.released_after': '<string>',
'submission_query.enabled': true,
'submission_query.completed_statuses': ['<string>'],
'submission_query.submission_collection_ids': ['<string>'],
callback_url: '<string>',
include_lessons: true,
include_submissions: true
})
};
fetch('https://{subdomain}.conveyour.com/api/compliance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{subdomain}.conveyour.com/api/compliance"
payload = {
"group_id": "<string>",
"contact_query": {},
"content_query.lesson_tags.all": ["<string>"],
"content_query.lesson_tags.any": ["<string>"],
"content_query.completed_after": "<string>",
"content_query.released_only": True,
"content_query.released_after": "<string>",
"submission_query.enabled": True,
"submission_query.completed_statuses": ["<string>"],
"submission_query.submission_collection_ids": ["<string>"],
"callback_url": "<string>",
"include_lessons": True,
"include_submissions": True
}
headers = {
"x-conveyour-token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{subdomain}.conveyour.com/api/compliance",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'group_id' => '<string>',
'contact_query' => [
],
'content_query.lesson_tags.all' => [
'<string>'
],
'content_query.lesson_tags.any' => [
'<string>'
],
'content_query.completed_after' => '<string>',
'content_query.released_only' => true,
'content_query.released_after' => '<string>',
'submission_query.enabled' => true,
'submission_query.completed_statuses' => [
'<string>'
],
'submission_query.submission_collection_ids' => [
'<string>'
],
'callback_url' => '<string>',
'include_lessons' => true,
'include_submissions' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-conveyour-token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"contact_query": {
"badge_number": 1234
},
"content_query": {
"lesson_tags": {
"all": [
"required-training"
]
},
"completed_after": "-1 year",
"released_only": true
},
"submission_query": {
"enabled": true,
"completed_statuses": [
"completed"
],
"submission_collection_ids": []
},
"callback_url": "",
"include_lessons": true,
"include_submissions": true
}{
"status": "failed",
"message": "Lacking necessary permission add_contacts",
"data": {
"permission": "add_contacts"
}
}Create a compliance run
Runs a compliance check against one or more contacts. Returns per-contact results inline (sync) or delivers them to a webhook URL (async).
Run a compliance check (sync or async)
Permission: Org admin only. Denials read Manage Compliance.
Not callable with an API key. Requires an org admin. Service accounts cannot be assigned the admin role and their role cannot be changed, so every API key gets 403. Only a signed-in admin can call it.
content_query.released_only is forced to true. The handler overwrites whatever you send before building the query, so a compliance run always considers released content only.
curl --request POST \
--url https://{subdomain}.conveyour.com/api/compliance \
--header 'Content-Type: application/json' \
--header 'x-conveyour-token: <api-key>' \
--data '
{
"group_id": "<string>",
"contact_query": {},
"content_query.lesson_tags.all": [
"<string>"
],
"content_query.lesson_tags.any": [
"<string>"
],
"content_query.completed_after": "<string>",
"content_query.released_only": true,
"content_query.released_after": "<string>",
"submission_query.enabled": true,
"submission_query.completed_statuses": [
"<string>"
],
"submission_query.submission_collection_ids": [
"<string>"
],
"callback_url": "<string>",
"include_lessons": true,
"include_submissions": true
}
'const options = {
method: 'POST',
headers: {'x-conveyour-token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
group_id: '<string>',
contact_query: {},
'content_query.lesson_tags.all': ['<string>'],
'content_query.lesson_tags.any': ['<string>'],
'content_query.completed_after': '<string>',
'content_query.released_only': true,
'content_query.released_after': '<string>',
'submission_query.enabled': true,
'submission_query.completed_statuses': ['<string>'],
'submission_query.submission_collection_ids': ['<string>'],
callback_url: '<string>',
include_lessons: true,
include_submissions: true
})
};
fetch('https://{subdomain}.conveyour.com/api/compliance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const options = {
method: 'POST',
headers: {'x-conveyour-token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
group_id: '<string>',
contact_query: {},
'content_query.lesson_tags.all': ['<string>'],
'content_query.lesson_tags.any': ['<string>'],
'content_query.completed_after': '<string>',
'content_query.released_only': true,
'content_query.released_after': '<string>',
'submission_query.enabled': true,
'submission_query.completed_statuses': ['<string>'],
'submission_query.submission_collection_ids': ['<string>'],
callback_url: '<string>',
include_lessons: true,
include_submissions: true
})
};
fetch('https://{subdomain}.conveyour.com/api/compliance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{subdomain}.conveyour.com/api/compliance"
payload = {
"group_id": "<string>",
"contact_query": {},
"content_query.lesson_tags.all": ["<string>"],
"content_query.lesson_tags.any": ["<string>"],
"content_query.completed_after": "<string>",
"content_query.released_only": True,
"content_query.released_after": "<string>",
"submission_query.enabled": True,
"submission_query.completed_statuses": ["<string>"],
"submission_query.submission_collection_ids": ["<string>"],
"callback_url": "<string>",
"include_lessons": True,
"include_submissions": True
}
headers = {
"x-conveyour-token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{subdomain}.conveyour.com/api/compliance",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'group_id' => '<string>',
'contact_query' => [
],
'content_query.lesson_tags.all' => [
'<string>'
],
'content_query.lesson_tags.any' => [
'<string>'
],
'content_query.completed_after' => '<string>',
'content_query.released_only' => true,
'content_query.released_after' => '<string>',
'submission_query.enabled' => true,
'submission_query.completed_statuses' => [
'<string>'
],
'submission_query.submission_collection_ids' => [
'<string>'
],
'callback_url' => '<string>',
'include_lessons' => true,
'include_submissions' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-conveyour-token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"contact_query": {
"badge_number": 1234
},
"content_query": {
"lesson_tags": {
"all": [
"required-training"
]
},
"completed_after": "-1 year",
"released_only": true
},
"submission_query": {
"enabled": true,
"completed_statuses": [
"completed"
],
"submission_collection_ids": []
},
"callback_url": "",
"include_lessons": true,
"include_submissions": true
}{
"status": "failed",
"message": "Lacking necessary permission add_contacts",
"data": {
"permission": "add_contacts"
}
}Authorizations
Your API key token. Contacts endpoints require a Server-only — Full API key — see Authentication.
Query Parameters
Team scope for the request, as one or more team ObjectIds. The brackets are required: PHP keeps only the last value for a repeated plain key, so teams=A&teams=B silently resolves to B alone. On requests with a JSON body you may send teams (no brackets) in the body instead.
Values that are not valid ObjectIds are silently ignored — a mistyped team ID behaves as if no team was sent. See the teams section of the API conventions guide.
Body
ID of a group whose filters define the contact audience.
A filter object matching contacts by field values. An empty object {} matches all contacts — use with care.
Lesson must have every tag in this list to be in scope.
Lesson must have at least one tag in this list to be in scope.
Relative time string — only completions after this window count (e.g. "-1 year").
When true, only lessons released to the contact via campaigns or triggers count.
Optional. Only lessons released after this time count.
Include form submissions in the compliance run.
Submission status values that count as done. Default ["completed"].
Limit scoring to specific collection IDs. Empty array includes all collections.
Set to an HTTPS URL for async mode — results are POSTed to your webhook. Omit or send "" for sync mode.
Include per-lesson detail rows in each contact result.
Include per-submission detail rows in each contact result.
Response
Success.
The common response envelope shared by all ConveYour endpoints.