SDK Reference

Last Updated: 2026-02-17 SDK Versions: JavaScript 1.0.0 | Python 1.0.0

npm versionnpm version PyPI versionPyPI version


Overview#

cloak.business provides official SDKs for JavaScript/TypeScript and Python.

Package Links:

Source Code: SDK_packages/ folder in the cloak.business repository

  • JavaScript SDK: SDK_packages/sdk-js/
  • Python SDK: SDK_packages/sdk-python/

These SDKs offer:

  • Type-safe API access with full TypeScript/Python type hints
  • Automatic error handling with typed error classes
  • Retry logic with exponential backoff
  • Client-side encryption for true zero-knowledge security
  • All API endpoints wrapped in convenient methods

Table of Contents#

  1. JavaScript/TypeScript SDK
  2. Python SDK
  3. Security Model
  4. Best Practices
  5. FAQ

JavaScript/TypeScript SDK#

Installation#

npm install @cloak-business/sdk
# or
yarn add @cloak-business/sdk
# or
pnpm add @cloak-business/sdk

Requirements: Node.js 18+ or modern browser with Web Crypto API

Quick Start#

import { CloakClient } from '@cloak-business/sdk';

// Initialize client
const client = new CloakClient({
  apiKey: process.env.CLOAK_API_KEY!,
});

// Analyze text for PII
const analysis = await client.analyze({
  text: 'Contact John Doe at john@example.com',
  language: 'en',
});

console.log(`Found ${analysis.results.length} entities`);

// Anonymize the text
const anonymized = await client.anonymize({
  text: 'Contact John Doe at john@example.com',
  analyzerResults: analysis.results,
  operators: {
    PERSON: { type: 'replace', new_value: '[REDACTED]' },
    EMAIL_ADDRESS: { type: 'hash', hash_type: 'sha256' },
  },
});

console.log(anonymized.text);
// Output: "Contact [REDACTED] at 3c4a7b8d9e0f..."

Client Configuration#

import { CloakClient, CloakClientConfig } from '@cloak-business/sdk';

const config: CloakClientConfig = {
  // Required
  apiKey: 'cb_your_api_key_here',

  // Optional
  baseUrl: 'https://cloak.business/api',  // Default
  timeout: 30000,                          // 30 seconds
  maxRetries: 3,                           // Retry failed requests
};

const client = new CloakClient(config);

Text Analysis#

Basic Analysis

const result = await client.analyze({
  text: 'My SSN is 123-45-6789',
  language: 'en',
});

// Result:
// {
//   results: [
//     { entity_type: 'US_SSN', start: 10, end: 21, score: 0.95, text: '123-45-6789' }
//   ],
//   tokens_charged: 2
// }

With Options

const result = await client.analyze({
  text: 'Call me at 555-123-4567',
  language: 'en',
  entities: ['PHONE_NUMBER', 'EMAIL_ADDRESS'],  // Only detect these
  scoreThreshold: 0.7,                          // Minimum confidence
});

Batch Analysis

const result = await client.batchAnalyze({
  texts: [
    'Email: john@test.com',
    'Phone: 555-123-4567',
    'SSN: 123-45-6789',
  ],
  language: 'en',
});

// Access results by index
result.results.forEach((item, index) => {
  console.log(`Text ${index}: ${item.entities.length} entities found`);
});

Custom Recognizers

const result = await client.analyze({
  text: 'Employee ID: EMP-12345',
  adHocRecognizers: [
    {
      entityType: 'EMPLOYEE_ID',
      patterns: [
        { name: 'emp_pattern', regex: 'EMP-\\d{5}', score: 0.9 }
      ],
      context: ['employee', 'staff', 'worker'],
    },
  ],
});

Anonymization#

Basic Anonymization

// First analyze
const analysis = await client.analyze({ text: 'Contact John at john@test.com' });

// Then anonymize
const result = await client.anonymize({
  text: 'Contact John at john@test.com',
  analyzerResults: analysis.results,
});
// Default: replaces with <ENTITY_TYPE>
// Output: "Contact <PERSON> at <EMAIL_ADDRESS>"

Operator Types

const result = await client.anonymize({
  text: 'John Doe, SSN: 123-45-6789, email: john@test.com',
  analyzerResults: analysis.results,
  operators: {
    // Replace with custom value
    PERSON: { type: 'replace', new_value: '[NAME REDACTED]' },

    // Hash (one-way, irreversible)
    EMAIL_ADDRESS: { type: 'hash', hash_type: 'sha256' },

    // Mask partially
    US_SSN: { type: 'mask', masking_char: '*', chars_to_mask: 5, from_end: false },

    // Encrypt (reversible with key)
    PHONE_NUMBER: { type: 'encrypt', key: 'your-32-char-encryption-key!!' },

    // Remove completely
    CREDIT_CARD: { type: 'redact' },

    // Keep original (useful with presets)
    DATE_TIME: { type: 'keep' },
  },
});

Deanonymization (Decrypt)

// Store the anonymize result for later decryption
const anonymized = await client.anonymize({
  text: 'Contact John Doe',
  analyzerResults: [{ entity_type: 'PERSON', start: 8, end: 16, score: 0.85 }],
  operators: {
    PERSON: { type: 'encrypt', key: 'your-32-char-encryption-key!!' },
  },
});

// Later: decrypt
const decrypted = await client.deanonymize({
  text: anonymized.text,
  anonymizerResults: anonymized.items,
  operators: {
    PERSON: { type: 'decrypt', key: 'your-32-char-encryption-key!!' },
  },
});

console.log(decrypted.text); // "Contact John Doe"

Client-Side Encryption (JS)#

For true zero-knowledge security where encryption keys never leave your device, use the ClientCrypto module:

import { ClientCrypto } from '@cloak-business/sdk';

// Generate a random encryption key (store securely!)
const key = await ClientCrypto.generateKey();
console.log(key); // Base64-encoded 256-bit key

// Encrypt data locally
const encrypted = await ClientCrypto.encrypt(key, 'Sensitive data here');
// {
//   ciphertext: 'base64...',
//   iv: 'base64...',
//   version: 1
// }

// Decrypt locally
const decrypted = await ClientCrypto.decrypt(key, encrypted);
console.log(decrypted); // 'Sensitive data here'

// Encrypt/decrypt objects
const user = { name: 'John', ssn: '123-45-6789' };
const encryptedUser = await ClientCrypto.encryptObject(key, user);
const decryptedUser = await ClientCrypto.decryptObject<typeof user>(key, encryptedUser);

Password-Derived Keys

// Derive key from password (for user-based encryption)
const salt = ClientCrypto.generateSalt();
const key = await ClientCrypto.deriveKeyFromPassword(
  'user-password',
  salt,
  100000  // iterations (PBKDF2)
);

// Store the salt with the encrypted data (salt is not secret)

Security Notes

  • ClientCrypto uses AES-256-GCM (AEAD cipher)
  • Keys are 32 bytes (256 bits)
  • IVs are 12 bytes, randomly generated per encryption
  • All operations use the Web Crypto API (CSPRNG)

Error Handling (JS)#

import {
  CloakClient,
  CloakError,
  AuthenticationError,
  RateLimitError,
  InsufficientTokensError,
  ValidationError,
} from '@cloak-business/sdk';

try {
  const result = await client.analyze({ text: 'test' });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof InsufficientTokensError) {
    console.error('Not enough tokens. Please top up.');
  } else if (error instanceof ValidationError) {
    console.error('Invalid request:', error.message);
  } else if (error instanceof CloakError) {
    console.error(`API error: ${error.code} - ${error.message}`);
  }
}

Python SDK#

Installation (Python)#

pip install cloak-business

For client-side encryption:

pip install cloak-business[crypto]
# or
pip install cloak-business cryptography

Requirements: Python 3.9+

Quick Start (Python)#

from cloak_business import CloakClient

# Initialize client
client = CloakClient(api_key="cb_your_api_key_here")

# Analyze text
analysis = client.analyze(text="Contact John Doe at john@example.com")
print(f"Found {len(analysis.results)} entities")

# Anonymize
result = client.anonymize(
    text="Contact John Doe at john@example.com",
    analyzer_results=analysis.results,
    operators={
        "PERSON": {"type": "replace", "new_value": "[REDACTED]"},
        "EMAIL_ADDRESS": {"type": "hash", "hash_type": "sha256"},
    }
)
print(result.text)

Client Configuration (Python)#

from cloak_business import CloakClient, CloakClientConfig

config = CloakClientConfig(
    api_key="cb_your_api_key_here",
    base_url="https://cloak.business/api",  # Optional
    timeout=30.0,                            # Seconds
    max_retries=3,
)

client = CloakClient(config=config)
# or simply:
client = CloakClient(api_key="cb_your_api_key_here")

Text Analysis (Python)#

# Basic analysis
result = client.analyze(text="My SSN is 123-45-6789")

for entity in result.results:
    print(f"{entity.entity_type}: {entity.text} (score: {entity.score})")

# With options
result = client.analyze(
    text="Call 555-123-4567",
    language="en",
    entities=["PHONE_NUMBER", "EMAIL_ADDRESS"],
    score_threshold=0.7,
)

# Batch analysis
result = client.batch_analyze(
    texts=["Email: john@test.com", "Phone: 555-1234"],
    language="en",
)

# Custom recognizers
result = client.analyze(
    text="Order ID: ORD-123456",
    ad_hoc_recognizers=[
        {
            "entity_type": "ORDER_ID",
            "patterns": [{"name": "order", "regex": r"ORD-\d{6}", "score": 0.9}],
        }
    ],
)

Anonymization (Python)#

# Analyze first
analysis = client.analyze(text="John Doe, john@test.com, 555-1234")

# Anonymize with operators
result = client.anonymize(
    text="John Doe, john@test.com, 555-1234",
    analyzer_results=analysis.results,
    operators={
        "PERSON": {"type": "replace", "new_value": "[NAME]"},
        "EMAIL_ADDRESS": {"type": "hash", "hash_type": "sha256"},
        "PHONE_NUMBER": {"type": "mask", "masking_char": "*", "chars_to_mask": 4},
    }
)

print(result.text)
# Output: "[NAME], 3c4a7b8d..., ***-1234"

Encryption & Deanonymization

ENCRYPTION_KEY = "your-32-character-key-here!!"

# Encrypt
anonymized = client.anonymize(
    text="Contact John Doe",
    analyzer_results=[{"entity_type": "PERSON", "start": 8, "end": 16, "score": 0.85}],
    operators={"PERSON": {"type": "encrypt", "key": ENCRYPTION_KEY}},
)

# Later: decrypt
decrypted = client.deanonymize(
    text=anonymized.text,
    anonymizer_results=anonymized.items,
    operators={"PERSON": {"type": "decrypt", "key": ENCRYPTION_KEY}},
)

print(decrypted.text)  # "Contact John Doe"

Client-Side Encryption (Python)#

For true zero-knowledge encryption:

from cloak_business import ClientCrypto, ClientEncryptedData

# Check if cryptography library is available
if not ClientCrypto.is_available():
    print("Install cryptography: pip install cryptography")

# Generate a random key
key = ClientCrypto.generate_key()  # Base64-encoded 256-bit key

# Encrypt
encrypted: ClientEncryptedData = ClientCrypto.encrypt(key, "Sensitive data")

# Decrypt
decrypted = ClientCrypto.decrypt(key, encrypted)
print(decrypted)  # "Sensitive data"

# Object encryption
data = {"name": "John", "ssn": "123-45-6789"}
encrypted = ClientCrypto.encrypt_object(key, data)
decrypted = ClientCrypto.decrypt_object(key, encrypted)

# Password-derived keys
salt = ClientCrypto.generate_salt()
derived_key = ClientCrypto.derive_key_from_password(
    password="user-password",
    salt=salt,
    iterations=100000,
)

# Serialize for storage
encrypted_dict = ClientCrypto.encrypted_data_to_dict(encrypted)
restored = ClientCrypto.encrypted_data_from_dict(encrypted_dict)

Error Handling (Python)#

from cloak_business import (
    CloakClient,
    CloakError,
    AuthenticationError,
    RateLimitError,
    InsufficientTokensError,
    ValidationError,
    NetworkError,
    TimeoutError,
)

client = CloakClient(api_key="cb_your_key")

try:
    result = client.analyze(text="test")
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except InsufficientTokensError:
    print("Not enough tokens")
except ValidationError as e:
    print(f"Invalid request: {e.message}")
except TimeoutError:
    print("Request timed out")
except NetworkError:
    print("Network error")
except CloakError as e:
    print(f"API error: {e.code} - {e.message}")

Security Model#

Server-Side Encryption#

When using the encrypt operator through the API:

  • Encryption key is transmitted over HTTPS
  • Server encrypts data and immediately discards the key
  • Server never stores your encryption key
  • Convenient for most use cases

Client-Side Encryption (Zero-Knowledge)#

When using ClientCrypto:

  • Encryption key never leaves your device
  • All encryption/decryption happens locally
  • Server never sees plaintext or keys
  • Use for maximum security requirements

Choosing the Right Approach#

Use CaseRecommendation
General PII anonymizationServer-side (encrypt operator)
Regulatory compliance (GDPR, HIPAA)Server-side is compliant
Maximum security / zero-trustClient-side (ClientCrypto)
Performance-critical applicationsServer-side (less overhead)
Offline capability neededClient-side

Best Practices#

1. Secure Key Storage#

// DON'T: Hardcode keys
const key = "hardcoded-key"; // Bad!

// DO: Use environment variables
const key = process.env.ENCRYPTION_KEY;

// DO: Use a secrets manager
const key = await secretsManager.getSecret("cloak-encryption-key");

2. Error Handling#

// Always handle errors appropriately
try {
  const result = await client.analyze({ text });
} catch (error) {
  if (error instanceof RateLimitError) {
    await sleep(error.retryAfter * 1000);
    return retry();
  }
  throw error;
}

3. Batch Processing#

// DON'T: Make individual requests in a loop
for (const text of texts) {
  await client.analyze({ text }); // Slow!
}

// DO: Use batch endpoint
const result = await client.batchAnalyze({ texts });

4. Key Rotation#

// Store key version with encrypted data
const encrypted = {
  ...await ClientCrypto.encrypt(currentKey, data),
  keyVersion: 2,
};

// Decrypt with appropriate key version
const key = keyVersions[encrypted.keyVersion];
const decrypted = await ClientCrypto.decrypt(key, encrypted);

FAQ#

General Questions#

Q: Which SDK should I use? A: Choose based on your tech stack:

  • JavaScript/TypeScript SDK: For Node.js backends, React/Vue/Angular frontends, or any JavaScript environment
  • Python SDK: For Python backends, data pipelines, Jupyter notebooks, or ML workflows

Q: Are the SDKs open source? A: Yes. The SDK source code is available in the SDK_packages/ folder in the cloak.business repository. You can view the implementations, report issues, and contribute improvements.

Q: Do the SDKs support all API features? A: Yes. Both SDKs support 100% of the cloak.business API including:

  • Text analysis (single and batch)
  • Anonymization with all operators (replace, redact, hash, mask, encrypt)
  • Deanonymization (decrypt)
  • Image analysis and redaction
  • Account management (token balance, sessions)
  • Custom recognizers

Installation#

Q: What are the minimum requirements? A:

  • JavaScript SDK: Node.js 18+ or any modern browser with Web Crypto API
  • Python SDK: Python 3.9+

Q: How do I install the crypto extras for Python? A: Use the crypto extra: pip install cloak-business[crypto]. This installs the cryptography package needed for ClientCrypto.

Q: Do the SDKs work in browsers? A: The JavaScript SDK works in both Node.js and modern browsers. The Python SDK is designed for server-side use.

Client-Side Encryption#

Q: What's the difference between server-side and client-side encryption? A:

  • Server-side (encrypt operator): Key is sent over HTTPS, server encrypts, then discards the key immediately
  • Client-side (ClientCrypto): Key never leaves your device, all encryption/decryption happens locally

Q: Which encryption algorithm does ClientCrypto use? A: AES-256-GCM (AEAD cipher) with randomly generated 12-byte IVs. This is the same algorithm used by major password managers and secure messaging apps.

Q: Can I use my own encryption key? A: Yes. You can provide your own 32-byte (256-bit) key encoded as Base64, or derive a key from a password using deriveKeyFromPassword() with PBKDF2.

Q: What happens if I lose my encryption key? A: Data encrypted with a lost key cannot be recovered. Always securely back up your encryption keys. Consider using Shamir Secret Sharing for critical keys.

Error Handling#

Q: How do I handle rate limits? A: The SDKs include automatic retry with exponential backoff. If you receive a RateLimitError, check the retryAfter property for the recommended wait time in seconds.

Q: What errors should I handle? A: At minimum, handle these error types:

  • AuthenticationError: Invalid or expired API key
  • RateLimitError: Too many requests (check retryAfter)
  • InsufficientTokensError: Account needs more tokens
  • ValidationError: Invalid request parameters

Versioning#

Q: How are SDK versions numbered? A: Both SDKs use semantic versioning (MAJOR.MINOR.PATCH) and are always released with the same version number to ensure compatibility.

Q: Will SDK updates break my code? A: We follow semver strictly:

  • Patch updates (1.0.x): Bug fixes, no breaking changes
  • Minor updates (1.x.0): New features, backwards compatible
  • Major updates (x.0.0): Breaking changes (rare, with migration guides)


Document maintained by cloak.business Contact: support@cloak.business