Service Requirement Answers
The four endpoints that read, add, edit and delete a client's requirement answers on a service.
Overview
A requirement is the question a product asks at order time; what is managed here are the answers on a service. The questions themselves are defined on the product side.
An answer comes from one of two sources. Ones from a definition are tied to a product requirement and carry its type, its options and its module mapping. Free-form ones carry nothing but a label and some content, added by hand later, and they never reach the module.
Reference
Listing the Answers
Returns every requirement answer recorded on the service.
product comes from a definition, custom was added freely.text, select, radio, checkbox or file.curl 'https://panel.example.com/api/v1/admin/services/506/requirements' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/services/506/requirements', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/requirements');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Services()->GetServiceRequirements(['id' => 506]);
// 'response' changes shape by type: an array on file, text on the rest.
foreach ($response['data'] as $req) {
$answer = $req['type'] === 'file'
? array_column($req['response'], 'file_name')
: $req['response'];
}{
"data": [
{
"id": 12,
"requirement_id": 22,
"key": "product",
"name": "Game Name",
"type": "text",
"response": "Minecraft",
"response_mkey": "",
"field_options": []
}
]
}Adding an Answer
Adds a requirement answer to the service, either from a definition or free-form.
defined ties it to a definition, custom adds it freely. Defaults to defined.text or file. Defaults to text; a free-form requirement has no choice types.201. Same shape as one row of the list schema.curl -X POST 'https://panel.example.com/api/v1/admin/services/506/requirements' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"source":"custom","label":"Server Name","type":"text","content":"srv-01"}'const res = await fetch('https://panel.example.com/api/v1/admin/services/506/requirements', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: 'custom',
label: 'Server Name',
type: 'text',
content: 'srv-01',
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/requirements');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'source' => 'custom',
'label' => 'Server Name',
'type' => 'text',
'content' => 'srv-01',
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// On a choice type you send the OPTION'S ID; sending its text records the wrong thing.
$definition = Api::Products()->GetRequirement(['id' => 22])['data'];
$option = $definition['langs']['en']['options'][0];
Api::Services()->CreateServiceRequirement([
'id' => 506,
'source' => 'defined',
'requirement_id' => 22,
'response' => $option['id'],
]);Updating an Answer
Changes a text-based answer. File answers cannot be edited.
response_mkey is resolved again.curl -X PATCH 'https://panel.example.com/api/v1/admin/services/506/requirements/12' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"response":"Valheim"}'const res = await fetch('https://panel.example.com/api/v1/admin/services/506/requirements/12', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ response: 'Valheim' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/requirements/12');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['response' => 'Valheim']),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The way to change a file answer is delete-then-add.
Api::Services()->DeleteServiceRequirement(['id' => 506, 'req_id' => 12]);
Api::Services()->CreateServiceRequirement([
'id' => 506,
'source' => 'custom',
'label' => 'Contract',
'type' => 'file',
'file' => 'data:application/pdf;base64,' . base64_encode($pdf),
]);Deleting an Answer
Deletes the answer. On a file type the uploaded file is removed from disk as well.
curl -X DELETE 'https://panel.example.com/api/v1/admin/services/506/requirements/12' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/services/506/requirements/12', {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/506/requirements/12');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Services()->DeleteServiceRequirement([
'id' => 506,
'req_id' => 12,
]);Pitfalls
On the dropdown, single-choice and multiple-choice types the answer is the option's id from the definition. Sending the option's visible text raises no error but records the wrong value and leaves the module mapping unresolved. Read the ids from the product requirement definition.
The update endpoint answers file_not_editable on a file type. The only way to change one is to delete the record and add a new one; the delete also removes the uploaded file from disk, so nothing stale is left behind.
In the list the response field is an array on the file type and plain text on the rest. Code expecting one shape breaks on the first service with a file requirement, so check type before reading it.
A free-form requirement only sits on the record: with no definition behind it there is no module mapping either. If the answer has to do something on the server, define the requirement on the product side and add it here from that definition.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.