@i-coverservices/client-js-sdk
v1.0.6
Published
JS SDK for API-to-API integration with Customer REST API
Readme
Client JS SDK
TypeScript SDK for API-to-API integration with the iCover Services Customer REST API.
Provides a fully typed client for all endpoints including case management, candidate management, multimedia, service management, and more.
Table of Contents
- Installation
- Quick Start
- Authentication
- Namespace-based Type API
- API Reference
- Health Check
- Case Management — Customers
- Case Management — Drafts
- Case Management — Individual Drafts
- Case Management — Organisation Drafts
- Case Management — Screenings
- Case Management — Products
- Case Management — Additional Fees
- Candidate Management
- Multimedia Management
- Service Management
- Product Management
- Geolocation (Countries)
- Webhook Types
- Purchase Screening (Wrapper)
- Error Handling
- Logging
- Examples
- Development
Installation
npm install @i-coverservices/client-js-sdkRequirements: Node.js >= 18
Security note: Run the SDK on a patched Node.js LTS release: 22.23.4+, 24.22.1+ or 26.12.1+. These versions fix the high-severity runtime vulnerabilities from the October 21, 2026 Node.js security release (Brotli decoder RCE, TLS hostname verification bypasses, DNS). The fixes are in the Node.js runtime, so they cannot be shipped by this package. Node.js 18 and 20 are end-of-life and do not receive these fixes.
Quick Start
import { ClientSDK } from '@i-coverservices/client-js-sdk';
const sdk = new ClientSDK({
accountApiUrl: 'https://account-api.example.com',
clientApiUrl: 'https://client-api.example.com',
apiKey: 'your-api-key',
});
// Check connectivity
const health = await sdk.clientApi.healthCheck();
console.log('API alive:', health.alive);Authentication
The SDK handles authentication automatically. Provide your API key during initialization, and the SDK will:
- Authenticate with the account API using the API key.
- Cache the JWT access token.
- Automatically re-authenticate when the token expires or gets a 401 response.
const sdk = new ClientSDK({
accountApiUrl: 'https://account-api.example.com',
clientApiUrl: 'https://client-api.example.com',
apiKey: 'your-api-key',
});No manual token management is required.
Namespace-based Type API
The SDK exposes all request/response types through a clean namespace hierarchy. You never need deep imports:
import type { CaseManagement } from '@i-coverservices/client-js-sdk';
// Access nested types via namespaces
type Req = CaseManagement.Drafts.AddServiceToScreening.AddServiceToScreeningRequest;
type Res = CaseManagement.Drafts.AddServiceToScreening.AddServiceToScreeningResponse;
// Other domain namespaces
import type { CandidateManagement } from '@i-coverservices/client-js-sdk';
import type { MultimediaManagement } from '@i-coverservices/client-js-sdk';
import type { ServiceManagement } from '@i-coverservices/client-js-sdk';
import type { HealthCheck } from '@i-coverservices/client-js-sdk';Available Namespaces
| Namespace | Sub-namespaces |
|------------------------|-------------------------------------------------------------------------------------------|
| CaseManagement | Customers, Drafts, IndividualDrafts, OrganisationDrafts, Products, Screenings |
| CandidateManagement | GetInvitations, ResendInvitation, SendInvitation |
| MultimediaManagement | Customers > UploadFile, ListFiles |
| ServiceManagement | Services > GetProductSources, GetProductRequirements |
| HealthCheck | HealthCheckResponse |
Shared / Base Types
Common types and enums are available as direct imports:
import type {
NamedEntity,
Country,
Screening,
ScreeningDetails,
FieldValue,
MultimediaFieldValue,
BaseValueType,
ApiResponse,
ApiListResponse,
FilterableQuery,
} from '@i-coverservices/client-js-sdk';
import { Platform, ExportStatus, SourceOrigin } from '@i-coverservices/client-js-sdk';API Reference
All methods are available on sdk.clientApi.
Health Check
| Method | Description |
|-----------------|------------------------------|
| healthCheck() | Returns { alive: boolean } |
Case Management -- Customers
| Method | Description |
|-----------------------------------------|--------------------------------------------|
| getCustomerScreenings(params) | List screenings for a customer (paginated) |
| generateCustomerScreeningsXLS(params) | Request XLS export of screenings |
| getScreeningDetails(params) | Get detailed screening information |
| getScreeningServiceStatuses() | List available screening statuses |
| submitDraftScreening(params) | Submit/purchase a draft screening |
| getProducts(params) | List products for a customer (paginated) |
| generateProductsXLS(params) | Request XLS export of products |
| getExport(params) | Get export file or status |
| getNoteTypes() | List available note types |
Case Management -- Drafts
| Method | Description |
|----------------------------------------------------------------|---------------------------------------|
| addServiceToScreening(screeningId, payload) | Add a service to a draft screening |
| updateServiceInScreening(serviceIndex, screeningId, payload) | Update a service in a screening |
| removeServiceFromScreening(serviceIndex, screeningId) | Remove a service from a screening |
| deleteScreeningDraft(screeningId) | Delete an entire draft screening |
| getOrderSummary(screeningId) | Get pricing/order summary for a draft |
Case Management -- Individual Drafts
| Method | Description |
|--------------------------------------------------------|--------------------------------------|
| addIndividualScreeningDraft(payload) | Create an individual screening draft |
| updateIndividualScreeningDraft(screeningId, payload) | Update an individual screening draft |
Case Management -- Organisation Drafts
| Method | Description |
|----------------------------------------------------------|----------------------------------------|
| addOrganisationScreeningDraft(payload) | Create an organisation screening draft |
| updateOrganisationScreeningDraft(screeningId, payload) | Update an organisation screening draft |
Case Management -- Screenings
| Method | Description |
|---------------------------------------------------------------------------|-------------------------------------------|
| getScreeningServicesActivityHistory(screeningId, componentId) | Activity history for a component |
| getScreeningServicesApplicationProcessHistory(screeningId, componentId) | Process history for a component |
| getScreeningServiceInformation(screeningId, componentId) | Provided vs verified info for a component |
| getScreeningServiceAdditionalInformation(screeningId, componentId) | Additional info for a component |
| getScreeningAttachments(screeningId) | List all attachments on a screening |
| getSingleAttachment(screeningId, attachmentId) | Download a single attachment (Blob) |
| addAttachmentToScreening(screeningId, payload) | Attach file(s) to a screening |
| deleteAttachmentFromScreening(screeningId, attachmentId) | Delete an attachment |
| listCustomerNotes(screeningId, componentId) | List customer notes on a component |
| createCustomerNote(screeningId, componentId, payload) | Create a customer note |
| getScreeningReport(screeningId, params?) | Get report as PDF or JSON |
| listScreeningNotifications(screeningId) | List notifications for a screening |
Case Management -- Products
| Method | Description |
|---------------------------------------|------------------------------------|
| getProductDetails(productId) | Get details for a specific product |
| requestProductActivation(productId) | Request product activation |
Case Management -- Additional Fees
| Method | Description |
|-----------------------------------------|---------------------------|
| approveAdditionalFee(additionalFeeId) | Approve an additional fee |
| denyAdditionalFee(additionalFeeId) | Deny an additional fee |
Candidate Management
| Method | Description |
|-----------------------------|------------------------------|
| sendInvitation(payload) | Send a candidate invitation |
| getInvitations(params) | List invitations (paginated) |
| resendInvitation(payload) | Resend an invitation |
Multimedia Management
| Method | Description |
|------------------------------------------------|-------------------------------------|
| uploadFile(customerId, screeningId, payload) | Upload a file (base64) |
| listFiles(customerId, screeningId) | List uploaded files for a screening |
| deleteFile(customerId, screeningId, fileId) | Delete a file |
Service Management
| Method | Description |
|---------------------------------------------|-----------------------------------------------|
| getProductSources(serviceId, params) | Get sources for a product |
| getProductRequirements(serviceId, params) | Get requirements for a product |
| getProductFactsheet(serviceId) | Download a product factsheet (Blob) |
| getRequirementSampleDocument(sampleId) | Download a requirement sample document (Blob) |
Product Management
| Method | Description |
|-------------------------------|----------------------------------|
| getServiceTypes(customerId) | Get service types for a customer |
Geolocation (Countries)
| Method | Description |
|------------------|------------------------------|
| getCountries() | List all available countries |
Webhook Types
The SDK provides fully typed webhook event payloads for all events the API can send. The types use a discriminated union on the action field, so switch(event.action) gives you full type narrowing in TypeScript.
Supported Events
| Action | Event Type | Description |
|----------------------------|---------------------------------|------------------------------------------|
| customerNoteAdded | CustomerNoteAddedEvent | A new customer note was added |
| screeningStateChange | ScreeningStateChangeEvent | Screening state changed (e.g. completed) |
| screeningReportGenerated | ScreeningReportGeneratedEvent | Screening report was generated |
| actionAdded | ActionAddedEvent | A new action was added to a service |
| newETA | NewETAEvent | Screening ETA has changed |
| additionalFeeRequest | AdditionalFeeRequestEvent | An additional fee approval is requested |
| attachmentAdded | AttachmentAddedEvent | An attachment was added to a service |
Usage (NestJS Example)
import type { WebhookEvent } from '@i-coverservices/client-js-sdk';
import { Controller, Post, Body, Headers } from '@nestjs/common';
@Controller('webhooks')
export class WebhookController {
@Post('api')
handleWebhook(
@Body() event: WebhookEvent,
@Headers('x-request-signature') signature: string,
) {
// TypeScript narrows the `data` type automatically
switch (event.action) {
case 'customerNoteAdded':
console.log('Note:', event.data.note.message);
break;
case 'screeningStateChange':
console.log('New state:', event.data.state);
break;
case 'screeningReportGenerated':
console.log('Report for:', event.data.soi.name.firstName);
console.log('Services:', event.data.services.length);
break;
case 'actionAdded':
console.log('Action needed:', event.data.action.actionNeeded);
break;
case 'newETA':
console.log('New ETA:', event.data.eta);
break;
case 'additionalFeeRequest':
console.log('Fee ID:', event.data.action.metadata.additionalFeeId);
break;
case 'attachmentAdded':
console.log('File:', event.data.attachment.filename);
break;
}
}
}Namespace Access
All webhook types are also available via the Webhooks namespace:
import type { Webhooks } from '@i-coverservices/client-js-sdk';
type Event = Webhooks.WebhookEvent;
type NoteEvent = Webhooks.CustomerNoteAddedEvent;Signature Verification
Webhook requests include an X-Request-Signature header for integrity verification. To validate:
import { createHmac } from 'crypto';
function verifyWebhookSignature(
body: object,
signature: string,
saltKey: string,
): boolean {
const decoded = Buffer.from(signature, 'base64').toString('utf8');
const computed = createHmac('sha256', saltKey)
.update(JSON.stringify(body))
.digest('hex');
return decoded === computed;
}Purchase Screening (Wrapper)
The SDK provides a convenience method that handles the full-screening purchase flow in a single call:
- Creates a draft screening (individual or organization)
- Adds services to the screening
- Uploads files and attaches them to services
- Submits/purchases the screening
import { ClientSDK } from '@i-coverservices/client-js-sdk';
import type { PurchaseScreeningRequest } from '@i-coverservices/client-js-sdk';
const sdk = new ClientSDK({ /* ... */ });
const request: PurchaseScreeningRequest = {
customerId: 1,
type: 'individual',
individual: {
clientReferenceId: 'IND-001',
soi: {
name: { firstName: 'Jane', lastName: 'Doe' },
otherNames: [],
dob: '1985-03-20',
addresses: [],
},
},
services: [
{
id: 42,
fields: { firstName: 'Jane', lastName: 'Doe' },
},
],
attachments: [
{
screeningServiceIndex: 0,
typeId: 1,
files: [
{
filename: 'id-card.pdf',
contents: '<base64-encoded-content>',
metadata: { type: 'application/pdf' },
},
],
},
],
};
const result = await sdk.clientApi.purchaseScreening(request);
console.log('Screening ID:', result.screeningId);
console.log('Status:', result.submission.status);Error Handling
API errors are wrapped in the ApiError class:
import { ClientSDK, ApiError } from '@i-coverservices/client-js-sdk';
try {
await sdk.clientApi.getScreeningDetails({ customerId: 1, screeningId: 999 });
} catch (error) {
if (error instanceof ApiError) {
console.error('API Error:', error.message);
console.error('Code:', error.code);
console.error('Resource:', error.resource);
console.error('Method:', error.method);
}
}Logging
Pass a custom logger to the SDK to capture debug output:
import { ClientSDK, SDKLogger } from '@i-coverservices/client-js-sdk';
const logger: SDKLogger = {
debug: (msg, meta) => console.log(`[DEBUG] ${msg}`, meta),
warn: (msg, meta) => console.warn(`[WARN] ${msg}`, meta),
error: (msg, meta) => console.error(`[ERROR] ${msg}`, meta),
};
const sdk = new ClientSDK({
accountApiUrl: 'https://account-api.example.com',
clientApiUrl: 'https://client-api.example.com',
apiKey: 'your-api-key',
logger,
});The default NoopLogger suppresses all output.
Examples
See src/examples/ for runnable examples covering every endpoint:
| File | Topics |
|------------------------------------|---------------------------------------------------|
| 01-authentication.ts | SDK init, custom logger, NoopLogger |
| 02-health-check.ts | API health check |
| 03-case-management-screenings.ts | List screenings, details, XLS export |
| 04-drafts-and-services.ts | Create drafts, add/update services, order summary |
| 05-purchase-screening-wrapper.ts | purchaseScreening() convenience method |
| 06-screening-attachments.ts | Upload files, attach, download, customer notes |
| 07-screening-reports.ts | PDF/JSON reports, activity history |
| 08-candidate-management.ts | Invitations: send, list, resend |
| 09-products-and-services.ts | Products, sources, requirements, factsheets |
| 10-additional-fees.ts | Approve/deny additional fees |
| 11-error-handling.ts | ApiError handling pattern |
Development
Build
npm run build # Builds both CJS and ESM
npm run build:cjs # CommonJS only
npm run build:esm # ES Modules onlyTest
npm test # Run all tests
npm run test:ci # Run tests sequentially (CI)Release
Releases are published to npmjs from a clean working tree, on the Node.js version pinned in .nvmrc:
nvm use
npm run release # npm version patch && npm publish --access publicnpm version patch bumps the version, commits it (e.g. 1.0.6) and creates a vX.Y.Z git tag.
prepublishOnly runs npm run test:ci and npm run build before publishing, so a failing test or build aborts the release.
Push the branch and the tag afterwards (git push && git push origin vX.Y.Z).
Project Structure
src/
├── index.ts # Main barrel — SDK, types, namespaces
├── sdk.ts # ClientSDK class
├── auth/ # Authentication & token management
├── client/
│ ├── client-api.ts # All API methods + purchaseScreening wrapper
│ ├── types.ts # Shared base types & enums
│ └── types/ # Domain-specific request/response types
│ ├── case-management/
│ │ ├── customers/
│ │ ├── drafts/
│ │ ├── individual-drafts/
│ │ ├── organisation-drafts/
│ │ ├── products/
│ │ └── screenings/
│ ├── candidate-management/
│ ├── multimedia-management/
│ ├── service-management/
│ └── health-check/
├── examples/ # Usage examples
├── helpers/ # Query param helpers
├── http/ # HTTP client, error types
└── logger/ # Logger interface & NoopLogger
tests/
├── auth/ # TokenManager tests
├── client/ # Unit tests (mirrors src structure)
└── http/ # HttpClient tests against a local HTTP server (real axios)