Client Documents

8 Aufrufe Markdown

The six endpoints that read a client's submitted documents, approve or reject them, and manage the canned rejection reasons.

Overview

A client fills in the fields the document scheme asks for and submits them; these endpoints read those submissions and settle them. The scheme itself is a separate job and lives in Document Scheme.

Each record maps to one field and carries its own status. A client can have some documents approved while others are still waiting.

Reference

Fetching Documents

get/api/v1/admin/clients/{id}/documents
Clients/GetClientDocuments admin marks as read

Returns the document records the client submitted. Records hang off the field id and every filter is merged into one list.

Query parameter 1
filter_idintIf given, the list narrows to the records that came from that filter.
Response fields data — 2
filtersobject[]The filters the returned records came from: [{ id, name }].
recordsobject[]The document records.
idintId of the document record. This is the key you use in the review request.
field_keyintId of the field in the shared pool.
field_namestringThe field label. Refreshed from the pool; if the field was deleted, the copy taken at submission comes back.
field_typestringInput type: input, textarea, selectbox, radio, checkbox, file.
field_valuestringThe value the client submitted. On file fields, JSON carrying the upload identifier.
filter_idintThe filter this record came from.
statusstringawaiting, verified or unverified.
status_msgstringThe review note; a rejection reason goes here.
Errors 2
not_found404No such client or record.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/clients/42/documents' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/clients/42/documents', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();

const waiting = body.data.records.filter((r) => r.status === 'awaiting');
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/documents');
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()->GetClientDocuments(['id' => 42]);

$waiting = [];
foreach ($response['data']['records'] as $record) {
    if ($record['status'] === 'awaiting') {
        $waiting[] = $record['id'];
    }
}

Reviewing Documents

patch/api/v1/admin/clients/{id}/documents
Clients/ReviewClientDocuments admin notifies the client

Updates the verification status of several records at once. Every record whose status changes sends the client a notification.

Body 1
statusesobjectrequiredA map keyed by record id: {"<recordId>": {"status": …, "message": …}}.
statusstringrequiredverified, unverified or awaiting. A record carrying anything else is skipped in silence.
messagestringThe review note. Put the reason here when rejecting; the client sees it.
Response fields data — 3
reviewedboolWhether the review was processed.
verifiedintHow many records were approved.
rejectedintHow many records were rejected.
Errors 2
not_found404No such client, or the client has no records at all.
insufficient_scope403The key lacks the required scope.
Request
curl -X PATCH 'https://panel.example.com/api/v1/admin/clients/42/documents' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"statuses":{"51":{"status":"verified"},"52":{"status":"unverified","message":"The document is unreadable, please send a clearer copy"}}}'
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/documents', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    statuses: {
      51: { status: 'verified' },
      52: { status: 'unverified', message: 'The document is unreadable, please send a clearer copy' },
    },
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/documents');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'statuses' => [
            51 => ['status' => 'verified'],
            52 => ['status' => 'unverified', 'message' => 'The document is unreadable, please send a clearer copy'],
        ],
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->ReviewClientDocuments([
    'id'       => 42,
    'statuses' => [
        51 => ['status' => 'verified'],
        52 => ['status' => 'unverified', 'message' => 'The document is unreadable, please send a clearer copy'],
    ],
]);

$rejected = $response['data']['rejected'] ?? 0;
Response
{
  "data": {
    "reviewed": true,
    "verified": 1,
    "rejected": 1
  }
}

Deleting a Document Record

delete/api/v1/admin/clients/{id}/documents/{record_id}
Clients/DeleteClientDocument admin

Deletes a single document record.

Response fields data — 2
deletedboolWhether the delete succeeded.
idintId of the deleted record.
Errors 3
not_found404No such client.
record_required422The record id was missing.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/clients/42/documents/51' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/documents/51', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/documents/51');
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()->DeleteClientDocument([
    'id'        => 42,
    'record_id' => 51,
]);

Listing Rejection Reasons

get/api/v1/admin/clients/document-rejection-reasons
Clients/GetDocumentRejectionReasons admin

Returns the saved rejection reasons. These are the canned texts used while reviewing.

Response fields data[]
datastring[]A plain list of reason texts — there are no ids here, the text itself is the identity.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/clients/document-rejection-reasons' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/clients/document-rejection-reasons', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-rejection-reasons');
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()->GetDocumentRejectionReasons();

Adding a Rejection Reason

post/api/v1/admin/clients/document-rejection-reasons
Clients/AddDocumentRejectionReason admin

Adds a new canned reason to the list.

Body 1
valuestringrequiredThe reason text.
Response fields data[]
datastring[]The whole list after the add, not the added text alone.
Errors 2
value_required422value was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/clients/document-rejection-reasons' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"value":"The document is unreadable, please send a clearer copy"}'
const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-rejection-reasons', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ value: 'The document is unreadable, please send a clearer copy' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-rejection-reasons');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['value' => 'The document is unreadable, please send a clearer copy']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->AddDocumentRejectionReason(['value' => 'The document is unreadable, please send a clearer copy']);

Deleting a Rejection Reason

delete/api/v1/admin/clients/document-rejection-reasons
Clients/DeleteDocumentRejectionReason admin deleted by text

Removes a reason from the list. You send the text itself, not an id.

Body 1
valuestringrequiredThe text of the reason to remove. It has to match the stored one exactly.
Response fields data[]
datastring[]The reasons that remain. A text that did not match leaves the list unchanged — compare it to know whether anything went.
Errors 2
value_required422value was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/clients/document-rejection-reasons' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"value":"The document is unreadable, please send a clearer copy"}'
const res = await fetch('https://panel.example.com/api/v1/admin/clients/document-rejection-reasons', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ value: 'The document is unreadable, please send a clearer copy' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/document-rejection-reasons');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['value' => 'The document is unreadable, please send a clearer copy']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->DeleteDocumentRejectionReason(['value' => 'The document is unreadable, please send a clearer copy']);

Pitfalls

Listing marks the records as read

The fetch endpoint is not read-only: calling it marks the records as read. An integration polling this while watching the pending-document badge will clear that badge on every poll.

A review notifies the client

Every record whose status changes sends an approval or rejection notice. Sending the same status twice counts as no change, but rejecting a record by mistake and fixing it produces two notices.

A rejection reason is deleted by its text

The delete request takes value, not an id, and the text has to match exactly. Even one space of difference will not find the record.

War das hilfreich?

Vielen Dank für Ihre Rückmeldung!

Brauchen Sie weitere Hilfe?

Unser Support-Team ist rund um die Uhr für Sie da, wenn Sie oben nicht fündig werden.