The official JavaScript/TypeScript SDK for Blindfold provides a simple and powerful way to protect sensitive data in your JavaScript and TypeScript applications. It works in both Node.js and browser environments.
Installation
Install the SDK using your preferred package manager:
npm install @blindfold/sdk
Initialization
Basic Setup (TypeScript)
import { Blindfold } from '@blindfold/sdk';
const client = new Blindfold({
apiKey: 'your-api-key-here'
});
Basic Setup (JavaScript)
const { Blindfold } = require('@blindfold/sdk');
const client = new Blindfold({
apiKey: 'your-api-key-here'
});
With Custom Configuration
import { Blindfold } from '@blindfold/sdk';
const client = new Blindfold({
apiKey: 'your-api-key-here',
baseUrl: 'https://api.blindfold.dev/api/public/v1', // Optional: Custom API endpoint
userId: 'user_123' // Optional: Track specific user for audit logs
});
Core Methods
Tokenize
Replace sensitive data with reversible tokens. Perfect for AI interactions where you need to restore original values later.
const response = await client.tokenize(
"Contact John Doe at [email protected] or call +1-555-1234",
{
entities: ['PERSON', 'EMAIL_ADDRESS', 'PHONE_NUMBER'], // Optional: Filter specific entities
score_threshold: 0.4 // Optional: Confidence threshold (0.0-1.0)
}
);
console.log(response.text);
// "Contact <PERSON_1> at <EMAIL_ADDRESS_1> or call <PHONE_NUMBER_1>"
console.log(response.mapping);
// {'<PERSON_1>': 'John Doe', '<EMAIL_ADDRESS_1>': '[email protected]', '<PHONE_NUMBER_1>': '+1-555-1234'}
console.log(response.entities_count);
// 3
response.detected_entities.forEach(entity => {
console.log(`${entity.entity_type}: ${entity.text} (confidence: ${entity.score.toFixed(2)})`);
});
Parameters:
text (string, required): The text to tokenize
config (object, optional):
entities (string[]): Array of entity types to detect
score_threshold (number): Minimum confidence score (0.0-1.0)
Returns: TokenizeResponse with:
text: Anonymized text with tokens
mapping: Object mapping tokens to original values
detected_entities: Array of detected entities with details
entities_count: Total number of entities found
Detokenize
Restore original values from tokens.
const original = await client.detokenize(
"AI response for <PERSON_1> at <EMAIL_ADDRESS_1>",
response.mapping
);
console.log(original.text);
// "AI response for John Doe at [email protected]"
console.log(original.replacements_made);
// 2
Parameters:
text (string, required): Text containing tokens
mapping (object, required): Token-to-value mapping from tokenize response
Returns: DetokenizeResponse with:
text: Original text with tokens replaced
replacements_made: Number of token replacements
Mask
Partially hide sensitive data (e.g., ****-****-****-1234).
const response = await client.mask(
"Credit card: 4532-7562-9102-3456",
{
masking_char: '*',
chars_to_show: 4,
from_end: true
}
);
console.log(response.text);
// "Credit card: ***************3456"
Parameters:
text (string, required): Text to mask
config (object, optional):
masking_char (string): Character to use for masking (default: *)
chars_to_show (number): Number of characters to keep visible (default: 4)
from_end (boolean): Show characters from end if true, start if false (default: true)
Returns: MaskResponse with:
text: Masked text
detected_entities: Array of detected and masked entities
entities_count: Number of entities masked
Redact
Permanently remove sensitive data.
const response = await client.redact(
"My SSN is 123-45-6789 and password is secret123",
{
entities: ['US_SSN'] // Optional: specific entities to redact
}
);
console.log(response.text);
// "My SSN is <US_SSN> and password is <PASSWORD>"
Parameters:
text (string, required): Text to redact
config (object, optional):
entities (string[]): Specific entity types to redact
score_threshold (number): Minimum confidence score
Returns: RedactResponse with:
text: Redacted text
detected_entities: Array of redacted entities
entities_count: Number of entities redacted
Hash
Replace data with deterministic hashes. Useful for analytics and matching without exposing original values.
const response = await client.hash(
"User ID: [email protected] purchased item X",
{
hash_type: 'sha256',
hash_prefix: 'ID_',
hash_length: 16
}
);
console.log(response.text);
// "User ID: ID_a3f8b9c2d4e5f6g7 purchased item X"
Parameters:
text (string, required): Text to hash
config (object, optional):
hash_type (string): Hash algorithm - md5, sha1, sha224, sha256, sha384, sha512 (default: sha256)
hash_prefix (string): Prefix for hash values (default: "")
hash_length (number): Length of hash to use (default: 16)
Returns: HashResponse with:
text: Text with hashed entities
detected_entities: Array of hashed entities
entities_count: Number of entities hashed
Synthesize
Replace real data with realistic fake data using Faker.
const response = await client.synthesize(
"John lives in New York and works at Microsoft",
{
language: 'en'
}
);
console.log(response.text);
// "Michael Smith lives in Boston and works at TechCorp" (example output)
Parameters:
text (string, required): Text to synthesize
config (object, optional):
language (string): Language code for fake data - en, cs, de, fr, es, it, pl, sk (default: en)
entities (string[]): Specific entity types to synthesize
score_threshold (number): Minimum confidence score
Returns: SynthesizeResponse with:
text: Text with synthesized data
detected_entities: Array of replaced entities
entities_count: Number of entities synthesized
Encrypt
Encrypt sensitive data using AES encryption (reversible with key).
const response = await client.encrypt(
"Secret message: API key is sk-12345",
{
encryption_key: 'your-secure-key-min-16-chars'
}
);
console.log(response.text);
// "Secret message: gAAAAABh..." (encrypted string)
Parameters:
text (string, required): Text to encrypt
config (object, optional):
encryption_key (string): Encryption key (min 16 characters)
entities (string[]): Specific entity types to encrypt
score_threshold (number): Minimum confidence score
Returns: EncryptResponse with:
text: Text with encrypted entities
detected_entities: Array of encrypted entities
entities_count: Number of entities encrypted
TypeScript Support
The SDK is written in TypeScript and provides full type definitions:
import {
Blindfold,
TokenizeResponse,
DetokenizeResponse,
MaskResponse,
DetectedEntity
} from '@blindfold/sdk';
const client = new Blindfold({ apiKey: 'your-api-key' });
// TypeScript knows the response type
const response: TokenizeResponse = await client.tokenize("Hello John");
// Autocomplete and type checking for entity properties
response.detected_entities.forEach((entity: DetectedEntity) => {
console.log(entity.entity_type); // TypeScript autocomplete works
console.log(entity.score); // Type-safe access
});
Supported Entity Types
The SDK automatically detects 50+ types of sensitive information:
PERSON - Person names
EMAIL_ADDRESS - Email addresses
PHONE_NUMBER - Phone numbers
DATE_TIME - Dates and times
CREDIT_CARD - Credit card numbers
IBAN_CODE - International Bank Account Numbers
CRYPTO - Cryptocurrency addresses
Government IDs
US_SSN - US Social Security Numbers
US_DRIVER_LICENSE - US Driver Licenses
US_PASSPORT - US Passport Numbers
NRP - National Registry Person (various countries)
MEDICAL_LICENSE - Medical license numbers
US_ITIN - Individual Taxpayer Identification Numbers
IP_ADDRESS - IP addresses (IPv4/IPv6)
URL - URLs and domains
API_KEY - API keys and tokens
LOCATION - Cities, addresses, and locations
ADDRESS - Physical addresses
And many more…
Error Handling
The SDK provides specific error classes for different scenarios:
import {
Blindfold,
AuthenticationError,
APIError,
NetworkError
} from '@blindfold/sdk';
const client = new Blindfold({ apiKey: 'invalid-key' });
try {
const response = await client.tokenize("Test");
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key:', error.message);
} else if (error instanceof APIError) {
console.error(`API error (${error.statusCode}):`, error.message);
} else if (error instanceof NetworkError) {
console.error('Network error:', error.message);
} else {
console.error('Unexpected error:', error);
}
}
Error Types:
AuthenticationError - Invalid or missing API key
APIError - API validation or processing errors (includes statusCode)
NetworkError - Connection issues, timeouts
Error - Unexpected errors
Configuration Options
Entity Filtering
Filter which types of entities to detect:
const response = await client.tokenize(
"Contact John at [email protected] or 555-1234",
{
entities: ['EMAIL_ADDRESS'] // Only detect emails
}
);
Confidence Threshold
Set minimum confidence score (0.0-1.0) for entity detection:
const response = await client.tokenize(
"Maybe this is an email: test@test",
{
score_threshold: 0.8 // Only high-confidence detections
}
);
Lower threshold = more detections (higher recall, lower precision)
Higher threshold = fewer detections (lower recall, higher precision)
Best Practices
1. Use Environment Variables for API Keys
// Node.js
const client = new Blindfold({
apiKey: process.env.BLINDFOLD_API_KEY
});
// Browser with build tool (e.g., Vite, Next.js)
const client = new Blindfold({
apiKey: import.meta.env.VITE_BLINDFOLD_API_KEY // Vite
// or
apiKey: process.env.NEXT_PUBLIC_BLINDFOLD_API_KEY // Next.js
});
Never expose API keys in client-side code in production. Use server-side API routes or edge functions.
2. Handle Errors Gracefully
async function protectData(text: string) {
try {
return await client.tokenize(text);
} catch (error) {
if (error instanceof AuthenticationError) {
// Handle auth error
throw new Error('Authentication failed');
} else if (error instanceof NetworkError) {
// Retry logic
return retryWithBackoff(() => client.tokenize(text));
}
throw error;
}
}
3. Store Mappings Securely
When using tokenization, store the mapping securely:
// Server-side (Node.js with Express)
app.post('/chat', async (req, res) => {
const { message } = req.body;
// Tokenize
const protected = await client.tokenize(message);
// Store mapping in session
req.session.tokenMapping = protected.mapping;
// Send to AI...
const aiResponse = await getAIResponse(protected.text);
// Detokenize
const final = await client.detokenize(aiResponse, req.session.tokenMapping);
res.json({ response: final.text });
});
4. Process Multiple Requests in Parallel
Framework Integration Examples
Next.js API Route
// app/api/protect/route.ts
import { Blindfold } from '@blindfold/sdk';
import { NextRequest, NextResponse } from 'next/server';
const client = new Blindfold({
apiKey: process.env.BLINDFOLD_API_KEY!
});
export async function POST(request: NextRequest) {
try {
const { text } = await request.json();
const response = await client.tokenize(text);
return NextResponse.json(response);
} catch (error) {
return NextResponse.json(
{ error: 'Failed to protect data' },
{ status: 500 }
);
}
}
Express.js Middleware
import express from 'express';
import { Blindfold } from '@blindfold/sdk';
const app = express();
const client = new Blindfold({
apiKey: process.env.BLINDFOLD_API_KEY!
});
app.use(express.json());
app.post('/api/tokenize', async (req, res) => {
try {
const { text } = req.body;
const response = await client.tokenize(text);
res.json(response);
} catch (error) {
res.status(500).json({ error: 'Failed to tokenize' });
}
});
app.listen(3000);
React Hook
// hooks/useBlindfold.ts
import { useState } from 'react';
export function useBlindfold() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const tokenize = async (text: string) => {
setLoading(true);
setError(null);
try {
// Call your API route, not directly from client
const response = await fetch('/api/protect', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
const data = await response.json();
return data;
} catch (err) {
setError(err as Error);
throw err;
} finally {
setLoading(false);
}
};
return { tokenize, loading, error };
}
Complete Example
Here’s a complete example integrating Blindfold with OpenAI in Node.js:
import { Blindfold } from '@blindfold/sdk';
import OpenAI from 'openai';
// Initialize clients
const blindfold = new Blindfold({
apiKey: process.env.BLINDFOLD_API_KEY!
});
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY!
});
async function chatWithPrivacy(userMessage: string): Promise<string> {
// 1. Tokenize sensitive data
const protected = await blindfold.tokenize(userMessage);
console.log(`Protected: ${protected.text}`);
// 2. Send protected text to OpenAI
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: protected.text }]
});
const aiResponse = completion.choices[0].message.content || '';
// 3. Detokenize AI response to restore original data
const final = await blindfold.detokenize(aiResponse, protected.mapping);
console.log(`Final: ${final.text}`);
return final.text;
}
// Usage
chatWithPrivacy("My name is John Doe and my email is [email protected]")
.then(response => console.log(response))
.catch(error => console.error(error));
Browser vs Node.js
The SDK works in both environments with some considerations:
Node.js
- Use environment variables for API keys
- Full access to all features
- Server-side API routes recommended
Browser
- Never expose API keys in client code
- Use server-side API routes or edge functions
- The SDK can be used in the browser, but authentication should happen server-side
// ❌ Bad - API key exposed in browser
const client = new Blindfold({
apiKey: 'sk-1234...' // Never do this!
});
// ✅ Good - API key on server
// Client calls your API route, which uses Blindfold SDK
fetch('/api/protect', {
method: 'POST',
body: JSON.stringify({ text: userInput })
});
Need Help?