Call Dockt from TypeScript
This guide shows how to call Dockt from a TypeScript backend using the public OpenAPI contract and a workspace credential.
The example uses native fetch. It creates an Assessment, uploads evidence, and reads the resulting 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', worker: { first_name: 'Amina', last_name: 'Diallo', date_of_birth: '1990-05-17', nationality: 'FR' }, context: [ { code: 'employment.relationship', value: 'posted_employee' }, { code: 'employment.employer_country', value: 'FR' } ] }, '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, collect those context values and update the Assessment before requesting evidence. The Assessment inputs reference explains each value type and code.
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 webhook or poll the canonical resource before reading a result.
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);} else 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.
- Verify and deduplicate signed webhooks.
- Reconcile unresolved resources with canonical API reads.
- Log
x-request-id, but never log credentials or document contents.
Continue with Receive webhooks and Test your integration.