Call Dockt from TypeScript
Use Dockt from your TypeScript backend to check a worker’s details and documents. This guide uses Dockt’s OpenAPI description to generate request and response types, so your editor can check the API calls.
The example uses native fetch and a workspace credential. It creates an Assessment, the case for one worker, uploads a document, and reads the saved result, called a Decision.
Before you begin
Section titled “Before you begin”In your own application project, make sure you have:
- Node.js 20 or another server runtime with
fetch,FormData, andBlob. - A workspace credential stored as
DOCKT_API_TOKEN. - TypeScript configured for your backend.
Never expose DOCKT_API_TOKEN to browser or mobile code.
Generate public API types
Section titled “Generate public API types”Generate a TypeScript declaration file from Dockt’s public OpenAPI URL:
npx openapi-typescript https://api.dockt.com/openapi.json \ --root-types \ --root-types-no-schema-prefix \ --output src/dockt-schema.d.tsThis command creates src/dockt-schema.d.ts in your project with the public request and response types.
Commit the generated file so you can review contract changes before updating your integration.
Create a Dockt client
Section titled “Create a Dockt client”In your application, create src/dockt.ts:
import type { Assessment, CreateAssessmentBody, Decision, Document, ProblemDetails} from './dockt-schema';
type SingleEnvelope<T> = { object: 'single'; data: T;};
export class DocktApiError extends Error { constructor( readonly status: number, readonly requestId: string | null, readonly problem: ProblemDetails | null ) { super(problem?.detail ?? `Dockt request failed with status ${status}.`); }}
export const createDocktClient = (token: string) => { const request = async <T>(path: string, init: RequestInit = {}) => { const headers = new Headers(init.headers); headers.set('authorization', `Bearer ${token}`); headers.set('accept', 'application/json');
const response = await fetch(new URL(path, 'https://api.dockt.com'), { ...init, headers }); const body = await response.json().catch(() => null);
if (!response.ok) { throw new DocktApiError( response.status, response.headers.get('x-request-id'), body as ProblemDetails | null ); }
return body as T; };
return { async createAssessment(body: CreateAssessmentBody, idempotencyKey: string) { const response = await request<SingleEnvelope<Assessment>>('/v1/assessments', { method: 'POST', headers: { 'content-type': 'application/json', 'idempotency-key': idempotencyKey }, body: JSON.stringify(body) }); return response.data; },
async getAssessment(assessmentId: string) { const response = await request<SingleEnvelope<Assessment>>( `/v1/assessments/${encodeURIComponent(assessmentId)}` ); return response.data; },
async uploadAssessmentDocument( assessmentId: string, file: Blob, filename: string, idempotencyKey: string ) { const form = new FormData(); form.set('file', file, filename);
const response = await request<SingleEnvelope<Document>>( `/v1/assessments/${encodeURIComponent(assessmentId)}/documents`, { method: 'POST', headers: { 'idempotency-key': idempotencyKey }, body: form } ); return response.data; },
async getDecision(decisionId: string) { const response = await request<SingleEnvelope<Decision>>( `/v1/decisions/${encodeURIComponent(decisionId)}` ); return response.data; } };};Do not set a multipart Content-Type header when you send FormData. Your runtime adds the required boundary.
Create an Assessment
Section titled “Create an Assessment”Use the client from your server code:
import { createDocktClient } from './dockt';
const dockt = createDocktClient(process.env.DOCKT_API_TOKEN!);
const assessment = await dockt.createAssessment( { external_id: 'worker-case-1042', inputs: [ { code: 'person.name.first', value: 'Amina', source: { kind: 'integration', reference: 'your_system:worker:1042' } }, { code: 'person.name.last', value: 'Diallo', source: { kind: 'integration', reference: 'your_system:worker:1042' } }, { code: 'person.date_of_birth', value: '1990-05-17', source: { kind: 'integration', reference: 'your_system:worker:1042' } }, { code: 'person.nationality', value: ['FR', 'MA'], source: { kind: 'integration', reference: 'your_system:worker:1042' } }, { code: 'employment.relationship', value: 'employee', source: { kind: 'integration', reference: 'your_system:assignment:1042' } }, { code: 'employment.posting_status', value: 'posted', source: { kind: 'integration', reference: 'your_system:assignment:1042' } } ] }, 'assessment-worker-case-1042');
console.log(assessment.id, assessment.input_requests, assessment.requirements);Store assessment.id and the idempotency key in your database before reporting success to the caller of your backend.
If input_requests contains entries, Dockt still needs those details for a check. Send values your system already knows through inputs, with their sources. Dockt continues any checks that have enough information.
Let users upload documents and see the result, including missing or incorrect evidence. Don’t ask them to complete a questionnaire. Complete an assessment shows how to send known values. Assessment inputs lists the field codes and value types.
Upload evidence
Section titled “Upload evidence”Read the file in your backend and upload it to the Assessment. This example uses a Blob, so it also works in server runtimes that don’t expose a filesystem:
const document = await dockt.uploadAssessmentDocument( assessment.id, new Blob([documentBytes], { type: 'application/pdf' }), 'passport.pdf', 'assessment-worker-case-1042-passport');
console.log(document.id, document.status);documentBytes is the file content your backend received from your application’s private upload or storage layer. Store document.id with that upload record.
The upload response normally has status: "uploaded" or status: "processing". Wait for a notification event or read the Document or Assessment again to check whether processing has finished.
Read the Decision
Section titled “Read the Decision”After assessment.completed, fetch the Assessment and its referenced Decision:
const current = await dockt.getAssessment(assessment.id);
if (current.input_requests.length > 0) { console.log('More context is required', current.input_requests);}if (!current.latest_decision) { console.log('Assessment processing is not complete');} else { const decision = await dockt.getDecision(current.latest_decision.decision_id); console.log(decision.decision, decision.findings, decision.requirements);}Store the Decision ID and assessment_input_version your application acts on. Before a delayed or high-impact action, fetch the Assessment again and confirm that its latest_decision.decision_id still matches.
Prepare the client for production
Section titled “Prepare the client for production”Add these controls in your application:
- Set connection and response timeouts.
- Retry only failures that can succeed later.
- Reuse the same idempotency key and body when retrying a create or upload.
- Configure a Notification Destination and deduplicate its events.
- Read unresolved resources again through the API to get their current state.
- Log
x-request-id, but never log credentials or document contents.
Continue with Notification destinations and Test your integration.