# @tholulwazi/verify-sdk

Official JavaScript/TypeScript SDK for the **Tholulwazi Verify Integration Platform**.

Use this SDK to build plugins for WordPress, WooCommerce, Shopify, Salesforce, HubSpot, Odoo, Sage, Xero, QuickBooks, ERPNext, SAP, and any other software platform.

> **Architecture:** Every plugin connects ONLY to `https://api.tholulwazicapital.co.za`. The SDK — and your end users — never communicate directly with verification providers. All provider routing is handled server-side by Tholulwazi Verify.

---

## Installation

```bash
npm install @tholulwazi/verify-sdk
```

```php
// PHP (Composer)
composer require tholulwazi/verify-sdk
```

```python
# Python
pip install tholulwazi-verify
```

---

## Quick Start

```javascript
const { TholulwaziVerify } = require('@tholulwazi/verify-sdk');

// Initialise with your API key
const client = new TholulwaziVerify({
  apiKey: 'live_tv_your_api_key_here',
});

// Run an identity verification
const result = await client.verify.identity({
  idNumber: '9001075696087',
  firstName: 'Dumisani',
  lastName: 'Dlamini',
  dateOfBirth: '1990-01-07',
});

console.log(result.recommendation); // 'approve' | 'review' | 'reject'
console.log(result.riskScore);      // 0–100
console.log(result.aiSummary);      // AI-generated summary
```

---

## Authentication

### API Key (recommended for server-to-server)
```javascript
const client = new TholulwaziVerify({ apiKey: 'live_tv_...' });
```

### User Session (for user-facing plugins)
```javascript
const client = new TholulwaziVerify({ refreshToken: storedRefreshToken });

// Login flow
const { userId } = await client.auth.loginWithCredentials(email, password);
const user = await client.auth.verifyOtp(userId, otpFromEmail);
```

### Sandbox Mode
```javascript
const client = TholulwaziVerify.sandbox('sandbox_tv_your_key');
// or
const client = new TholulwaziVerify({ apiKey: 'sandbox_tv_...', sandbox: true });
```

---

## Verification Methods

All methods return a Promise resolving to a verification result:
```typescript
{
  id: string;               // Transaction ID (UUID)
  recommendation: 'approve' | 'review' | 'reject';
  riskScore: number;        // 0–100
  riskBand: 'very_low' | 'low' | 'medium' | 'high';
  aiSummary: string;        // AI-generated explanation
  creditsCharged: number;
  status: 'completed';
  createdAt: string;        // ISO timestamp
}
```

### Identity Verification (1 credit)
```javascript
await client.verify.identity({
  idNumber: '9001075696087',
  firstName: 'Dumisani',
  lastName: 'Dlamini',
  dateOfBirth: '1990-01-07',   // optional but improves accuracy
});
```

### AML / PEP Screening (5 credits)
```javascript
await client.verify.amlScreening({
  name: 'John Doe',
  country: 'ZA',  // ISO 3166-1 alpha-2
  entity: 0,      // 0 = individual, 1 = company
});
```

### Bank Account Verification (6 credits)
```javascript
await client.verify.bankAccountVerification({
  type: 'Individual',
  firstName: 'Dumisani',
  surname: 'Dlamini',
  identityNumber: '9001075696087',
  identityType: 'IDNumber',
  bankAccountNumber: '1234567890',
  bankBranchCode: '632005',
  bankAccountType: 'Current',
});
```

### Company Verification / CIPC (10 credits)
```javascript
await client.verify.companyVerification({
  registrationNumber: '2021/123456/07',
});
```

### Director Search (10 credits)
```javascript
await client.verify.directorSearch({ idNumber: '9001075696087' });
```

### Consumer Trace (10 credits)
```javascript
await client.verify.consumerTrace({
  idNumber: '9001075696087',
  firstName: 'Dumisani',
  lastName: 'Dlamini',
});
```

### Vehicle Lookup (5 credits)
```javascript
await client.verify.vehicleLookup({ registrationNumber: 'CA123456' });
```

### VIN Decode (5 credits)
```javascript
await client.verify.vinDecode({ vin: 'JTDBU4EE2AJ050000' });
```

### Document OCR (3 credits)
```javascript
await client.verify.documentOcr({
  frontImageBase64: '...base64 encoded image...',
  backImageBase64: '...optional...',
});
```

### Face Match (1 credit)
```javascript
await client.verify.faceMatch({
  idImageRef: '...base64 ID photo...',
  selfieImageRef: '...base64 selfie...',
});
```

---

## Composite Verifications

### Verify Supplier (ERP/Accounting use case)
Runs identity + AML + bank account verification in a single API call:
```javascript
const result = await client.verify.verifySupplier({
  // Identity
  idNumber: '9001075696087',
  firstName: 'John',
  lastName: 'Doe',
  dateOfBirth: '1985-03-15',
  // Bank
  bankAccountNumber: '1234567890',
  bankBranchCode: '632005',
  bankAccountType: 'Current',
  // Optional: also runs CIPC company match
  registrationNumber: '2021/123456/07',
});
```

---

## Configuration Options

```javascript
const client = new TholulwaziVerify({
  apiKey: 'live_tv_...',           // API key auth
  sandbox: false,                   // Use production (default)
  timeout: 30000,                   // Request timeout ms
  maxRetries: 3,                    // Retry attempts on failure
  retryDelayMs: 1000,              // Base retry delay (exponential backoff)
  cache: {
    enabled: true,                  // Cache GET responses
    defaultTtlMs: 60000,           // 1 minute TTL
  },
  logging: {
    level: 'warn',                  // debug | info | warn | error | none
    handler: (level, msg) => {},    // Custom log handler
  },
  webhookSecret: 'your_secret',    // For webhook signature verification
  onTokenRefreshed: (token) => {}, // Callback on token refresh
  onAuthExpired: () => {},         // Callback on session expiry
});
```

---

## Webhook Processing

```javascript
// Express.js example
app.post('/webhooks/tholulwazi', express.raw({ type: 'application/json' }), (req, res) => {
  const payload = client.webhooks.verify(
    req.body.toString(),
    req.headers['x-tholulwazi-signature']
  );

  client.webhooks
    .on('verification.completed', async ({ data }) => {
      if (data.recommendation === 'reject') {
        await flagSupplier(data.id);
      }
    })
    .dispatch(payload);

  res.status(200).send('OK');
});
```

---

## Reports

```javascript
// Monthly summary
const summary = await client.reports.summary({ period: '30d' });

// Custom date range
const report = await client.reports.summary({
  period: 'custom',
  from: '2026-01-01',
  to: '2026-01-31',
});

// CSV export
const csv = await client.reports.exportCsv({ from: '2026-01-01', to: '2026-01-31' });
```

---

## Error Handling

```javascript
const { TholulwaziError, AuthError, QuotaError, ValidationError, NetworkError } = require('@tholulwazi/verify-sdk');

try {
  const result = await client.verify.identity({ idNumber: '...' });
} catch (err) {
  if (err instanceof ValidationError) {
    console.error('Invalid input:', err.message);
  } else if (err instanceof AuthError) {
    console.error('Authentication failed — check your API key');
  } else if (err instanceof QuotaError) {
    console.error('Rate limit or quota exceeded — slow down or top up credits');
  } else if (err instanceof NetworkError) {
    console.error('Network error:', err.message);
    // Item is automatically queued for retry if offline queue is enabled
  } else if (err instanceof TholulwaziError) {
    console.error(`API error (${err.status}):`, err.message);
  }
}
```

---

## Plugin Development Guide

### Minimal Plugin Template

```javascript
// plugin.js — Template for any platform integration
const { TholulwaziVerify } = require('@tholulwazi/verify-sdk');

class MyPlatformPlugin {
  constructor(settings) {
    this.client = new TholulwaziVerify({
      apiKey: settings.apiKey,
      sandbox: settings.sandboxMode,
      logging: { level: settings.debugMode ? 'debug' : 'warn' },
      webhookSecret: settings.webhookSecret,
    });
  }

  async verifyCustomer(customer) {
    return this.client.verify.identity({
      idNumber: customer.idNumber,
      firstName: customer.firstName,
      lastName: customer.lastName,
    });
  }

  async verifySupplier(supplier) {
    return this.client.verify.verifySupplier({
      idNumber: supplier.idNumber,
      firstName: supplier.firstName,
      lastName: supplier.lastName,
      bankAccountNumber: supplier.bankAccountNumber,
      bankBranchCode: supplier.bankBranchCode,
      registrationNumber: supplier.companyRegistration,
    });
  }

  displayResult(result) {
    return {
      riskScore: result.riskScore,
      recommendation: result.recommendation,
      summary: result.aiSummary,
      transactionId: result.id,
      checks: {
        identityVerified: result.results?.identity?.success,
        amlCleared: result.results?.aml_screening?.recommendation !== 'reject',
        bankMatched: result.results?.bank_account_verification?.recommendation === 'approve',
      },
    };
  }
}
```

---

## White-Label Support

Partners can configure custom branding via the Tholulwazi Verify dashboard:
- Company logo and colours
- Custom portal name
- Custom email templates
- Custom PDF reports
- Custom domain (e.g. verify.yourcompany.co.za)

The SDK respects all branding settings automatically — no code changes required.

---

## Support

- Documentation: https://verify.tholulwazicapital.co.za/developers/api
- SDK Reference: https://verify.tholulwazicapital.co.za/developers/sdks
- Email: support@tholulwazicapital.co.za
- API Status: https://api.tholulwazicapital.co.za/health

---

## Licence

MIT © Tholulwazi Capital (Pty) Ltd
