Document Scheme
The ten endpoints that define which document is asked of whom: the field pool and the filters that use it.
Overview
The document scheme has two layers. Fields are a shared pool — single inputs such as "passport copy" or "tax certificate". Filters pick a set out of that pool and carry the rules that decide who is asked for it.
One field can sit in several filters; that is what the pool is for. Updating a field reaches every filter using it at once.
Reference
Listing Filters
Returns the document filters. Each one carries a set of fields and the rules that decide who is asked for them.
active or inactive.active or inactive.email_provider, vpn_proxy, account_age, service_count, total_spending, country_mismatch, country.yes, a numeric threshold or a country id.curl -G 'https://panel.example.com/api/v1/admin/clients/document-filters' \
-H "Authorization: Bearer $API_KEY" \
-d status=activeconst url = new URL('https://panel.example.com/api/v1/admin/clients/document-filters');
url.searchParams.set('status', 'active');
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();$url = 'https://panel.example.com/api/v1/admin/clients/document-filters?' . http_build_query(['status' => 'active']);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->GetDocumentFilters([], ['status' => 'active']);Adding a Filter
Defines a new filter. The field ids have to exist in the pool.
[3, 1].false; the filter is born inactive.email_provider, vpn_proxy, account_age, service_count, total_spending, country_mismatch, country.yes, a numeric threshold or a country id.active or inactive. A new filter is born inactive unless you sent active.type / value / extra shape as the listing.name was empty.fields was empty or malformed.curl -X POST 'https://panel.example.com/api/v1/admin/clients/document-filters' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"name":"High spend","fields":[3,1],"active":true,"rules":[{"type":"total_spending","value":"5000","extra":""}]}'const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-filters', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"name":"High spend","fields":[3,1],"active":true,"rules":[{"type":"total_spending","value":"5000","extra":""}]}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-filters');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'name' => 'High spend',
'fields' => [3, 1],
'active' => true,
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->CreateDocumentFilter([
'name' => 'High spend',
'fields' => [3, 1],
'active' => true,
'rules' => [
['type' => 'total_spending', 'value' => '5000', 'extra' => ''],
],
]);Filter Detail
Returns one filter; the schema is the same as in the list.
active or inactive.type / value / extra shape as the listing.curl 'https://panel.example.com/api/v1/admin/clients/document-filters/7' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-filters/7', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-filters/7');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->GetDocumentFilter(['fid' => 7]);Updating a Filter
Changes the filter name, the field order, the status or the rules.
active or inactive.name was sent empty.fields was sent empty or malformed.curl -X PATCH 'https://panel.example.com/api/v1/admin/clients/document-filters/7' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"active":false}'const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-filters/7', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ active: false }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-filters/7');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['active' => false]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->UpdateDocumentFilter([
'fid' => 7,
'active' => false,
]);Deleting a Filter
Deletes the filter. The field pool is untouched; the fields stay in whatever other filters use them.
curl -X DELETE 'https://panel.example.com/api/v1/admin/clients/document-filters/7' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-filters/7', {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-filters/7');
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::Clients()->DeleteDocumentFilter(['fid' => 7]);Listing Fields
Returns the shared field pool. Filters pick their fields from here.
active or inactive.fields list points here.active or inactive. An inactive field is not shown to the client.input, textarea, selectbox, radio, checkbox, file.{"en": "Passport copy"}.file type.file type.[{ id, name }].curl -G 'https://panel.example.com/api/v1/admin/clients/document-fields' \
-H "Authorization: Bearer $API_KEY" \
-d type=fileconst url = new URL('https://panel.example.com/api/v1/admin/clients/document-fields');
url.searchParams.set('type', 'file');
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();$url = 'https://panel.example.com/api/v1/admin/clients/document-fields?' . http_build_query(['type' => 'file']);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->GetDocumentFields([], ['type' => 'file']);Adding a Field
Adds a field to the pool. The label has to be given in at least one language.
true.file type.file type.active or inactive.type is not one of the allowed input types.curl -X POST 'https://panel.example.com/api/v1/admin/clients/document-fields' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"type":"file","labels":{"en":"Passport copy"},"allowed_ext":"jpg,png,pdf","max_size":5}'const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-fields', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'file',
labels: {"en":"Passport copy"},
allowed_ext: 'jpg,png,pdf',
max_size: 5,
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-fields');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'type' => 'file',
'labels' => ['en' => 'Passport copy'],
'allowed_ext' => 'jpg,png,pdf',
'max_size' => 5,
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->CreateDocumentField([
'type' => 'file',
'labels' => ['en' => 'Passport copy'],
'allowed_ext' => 'jpg,png,pdf',
'max_size' => 5,
]);Field Detail
Returns one field. used_in comes with it, showing which filters use it.
fields list refers to.active or inactive. An inactive field is not shown to clients even where a filter still lists it.input, textarea, selectbox, radio, checkbox, file.{ "en": "Passport copy" }.file type only.file type only.{ id, name }. Read it before deleting — every one of them loses the field.curl 'https://panel.example.com/api/v1/admin/clients/document-fields/3' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-fields/3', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-fields/3');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->GetDocumentField(['fid' => 3]);
// Before deleting: which filters hold this field?
$usedIn = $response['data']['used_in'] ?? [];Updating a Field
Updates the field. The change reaches every filter using it at once.
true.file type.file type.active or inactive.type is not one of the allowed input types.curl -X PATCH 'https://panel.example.com/api/v1/admin/clients/document-fields/3' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"max_size":10}'const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-fields/3', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ max_size: 10 }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-fields/3');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['max_size' => 10]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Clients()->UpdateDocumentField([
'fid' => 3,
'max_size' => 10,
]);Deleting a Field
Removes the field from the pool.
curl -X DELETE 'https://panel.example.com/api/v1/admin/clients/document-fields/3' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-fields/3', {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-fields/3');
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::Clients()->DeleteDocumentField(['fid' => 3]);Pitfalls
fields is not a set but an ordered list, and the client sees the fields in that order. On update the list you send replaces the old one; it does not append to it.
Updating or deleting a field affects every filter that uses it. Look at used_in on the field detail before you delete.
Leave active out and the filter is created as inactive, asking nobody for anything. Creating one and walking away leaves a verification that never runs.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.