The PrivacyPal SDK lets you encode sensitive data into Privacy Twins before it reaches an AI model, then decode the response to restore original values. Available for both Node.js and Python — identical API surface, same endpoint, same behavior.
Async/await API. Works with Express, Next.js, Fastify, and any Node.js runtime.
npm install @privacypal/sdk
Synchronous API built on requests. Works with FastAPI, Django, Flask, and any Python 3.10+ runtime.
pip install privacypal-sdk
Install the SDK for your language. Both packages expose identical functionality.
npm install @privacypal/sdk
Requires Node.js 18 or later. TypeScript types are included.
pip install privacypal-sdk
Requires Python 3.10 or later. Installs requests as the only dependency.
Create a client instance with your API URL and API key. You can obtain an API key from the PrivacyPal Portal.
import { PrivacyPalClient } from '@privacypal/sdk'; const client = new PrivacyPalClient({ apiUrl: 'https://api.privacypal.ai', apiKey: process.env.PRIVACYPAL_API_KEY, }); // Verify connectivity (optional) const health = await client.healthCheck(); console.log(health.success); // true
from privacypal_sdk import PrivacyPalClient import os client = PrivacyPalClient( api_url='https://api.privacypal.ai', api_key=os.environ['PRIVACYPAL_API_KEY'], ) # Verify connectivity (optional) health = client.health_check() print(health['success']) # True
encode scans a string for PII and replaces sensitive values
with Privacy Twins. Returns encodedData that is safe to pass
to AI models, and a continuationId needed to decode later.
const encoded = await client.encode({ data: 'Patient: Jane Doe, DOB: 1985-03-15, SSN: 123-45-6789', sourceContainer: 'my-app', // identifies your application sourceElement: 'patient-record', // identifies the data field scoreThreshold: 0.35, // PII confidence threshold (default) language: 'en', // language hint (default) }); console.log(encoded.encodedData); // "Patient: [TWIN-A1B2], DOB: [TWIN-C3D4]..." console.log(encoded.continuationId); // keep this to decode later console.log(encoded.transformations); // list of PII replacements made
encoded = client.encode( 'Patient: Jane Doe, DOB: 1985-03-15, SSN: 123-45-6789', source_container='my-app', # identifies your application source_element='patient-record', # identifies the data field score_threshold=0.35, # PII confidence threshold (default) language='en', # language hint (default) ) print(encoded['encodedData']) # "Patient: [TWIN-A1B2], DOB: [TWIN-C3D4]..." print(encoded['continuationId']) # keep this to decode later print(encoded['transformations']) # list of PII replacements made
To encode multiple items in one request, use encodeBatch / encode_batch. To encode a file (PDF, DOCX, CSV, image), use encodeFile / encode_file.
Pass the continuationId from the encode response alongside
text containing Privacy Twins to restore original sensitive values.
// Encode first const encoded = await client.encode({ data: 'Call me at 555-867-5309, I am Sarah Connor', sourceContainer: 'chatbot', sourceElement: 'user-message' }); // Send encoded data to AI, get a response with Privacy Twins const aiReply = await callOpenAI(encoded.encodedData); // Decode the AI response — restore original values const decoded = await client.decode({ continuationId: encoded.continuationId, data: aiReply.content, sensitiveHashes: encoded.transformations.map(t => t.originalHash), authorization: { token: 'your-jwt', purpose: 'Display to user' }, }); console.log(decoded.decodedData); // Real names and numbers restored
# Encode first encoded = client.encode( 'Call me at 555-867-5309, I am Sarah Connor', source_container='chatbot', source_element='user-message' ) # Send encoded data to AI, get a response with Privacy Twins ai_reply = call_openai(encoded['encodedData']) # Decode the AI response — restore original values decoded = client.decode( continuation_id=encoded['continuationId'], data=ai_reply['content'], sensitive_hashes=[t['originalHash'] for t in encoded['transformations']], authorization={'token': 'your-jwt', 'purpose': 'Display to user'}, ) print(decoded['decodedData']) # Real names and numbers restored
Use chatWithAI to send prompts through PrivacyPal's AI gateway, which automatically encodes PII before forwarding
to the LLM and decodes the response.
const result = await client.chatWithAI({ prompt: 'Summarise the patient notes for Jane Doe.', model: 'gemini-2.0-flash-exp', provider: 'vertex', }); console.log(result.decodedResponse); // Decoded — real names in the answer
result = client.chat_with_ai( prompt='Summarise the patient notes for Jane Doe.', model='gemini-2.0-flash-exp', provider='vertex', ) print(result['decodedResponse']) # Decoded — real names in the answer
Node.js: Throws Error — check err.message for status prefixes. Python: Raises typed exceptions (AuthenticationError, TrialExpiredError, NetworkError).
| Exception / Pattern | HTTP Status | When it occurs |
|---|---|---|
| AuthenticationError / "401:" | 401 | Missing, expired, or invalid API key |
| TrialExpiredError / "403:" or "[Trial expired]" | 403 | Trial ended or subscription required |
| NetworkError / "Network Error:" | — | Cannot reach the API (connection refused, DNS failure) |
| RequestError / "Request Error:" | — | Request configuration error |
try { const encoded = await client.encode({ data: '...' }); } catch (err) { if (err.message?.startsWith('401:')) { console.error('Invalid or expired API key'); } else if (err.message?.startsWith('403:') || err.message?.includes('Trial expired')) { console.error('Subscription required'); } else if (err.message?.includes('Network Error')) { console.error('Cannot reach API'); } else { throw err; } }
from privacypal_sdk import ( PrivacyPalClient, AuthenticationError, TrialExpiredError, NetworkError, ) try: encoded = client.encode('...') except AuthenticationError: print('Invalid or expired API key') except TrialExpiredError: print('Subscription required') except NetworkError: print('Cannot reach API') except Exception as e: raise
Real workflows from production deployments — encode at the boundary, hand twins to an external agent or API, decode the response back to real values.
Encode the sensitive input, hand the twins off to an external agent, then decode the response back to original values.
const encoded = await client.encode({ data: 'User: John Smith, Email: john@acme.com, ID: user-123', sourceContainer: 'my-agent', sourceElement: 'user_input', }); // Share encoded data with an external agent const response = await sendToExternalAgent(encoded.encodedData); // Decode the response back to real values const decoded = await client.decode({ continuationId: encoded.continuationId, data: response.text, }); console.log(decoded.decodedData);
encoded = client.encode( 'User: John Smith, Email: john@acme.com, ID: user-123', source_container='my-agent', source_element='user_input', ) # Share encoded data with an external agent response = send_to_external_agent(encoded['encodedData']) # Decode the response back to real values decoded = client.decode( continuation_id=encoded['continuationId'], data=response['text'], ) print(decoded['decodedData'])
Encode PHI before sending to a vendor API, decode the analysis on the way back — HIPAA-compliant by design.
const encoded = await client.encode({ data: 'Patient: Jane Doe, DOB: 1985-03-15, Dx: Condition X', sourceContainer: 'ehr-system', sourceElement: 'patient-record', }); const analysis = await fetch('https://vendor-api.com/analyze', { method: 'POST', body: JSON.stringify({ data: encoded.encodedData }), }); const result = await client.decode({ continuationId: encoded.continuationId, data: (await analysis.json()).report, });
encoded = client.encode( 'Patient: Jane Doe, DOB: 1985-03-15, Dx: Condition X', source_container='ehr-system', source_element='patient-record', ) response = requests.post( 'https://vendor-api.com/analyze', json={'data': encoded['encodedData']}, ) result = client.decode( continuation_id=encoded['continuationId'], data=response.json()['report'], )
Encode trade info to protect trader identity, match through Privacy Twins, and (in a future release) decode only after x402 payment is settled.
// Future: import { x402Middleware } from '@x402/payment'; const encoded = await client.encode({ data: 'Trader: trader-789, Symbol: AAPL, Qty: 1000', sourceContainer: 'dark-pool', sourceElement: 'trade-request', }); const match = await findCounterparty(encoded.encodedData); if (match.found) { // Future: x402 payment required before decode const realData = await client.decode({ continuationId: encoded.continuationId, data: match.counterpartyData, }); return realData.decodedData; }
# Future: from x402 import middleware encoded = client.encode( 'Trader: trader-789, Symbol: AAPL, Qty: 1000', source_container='dark-pool', source_element='trade-request', ) match = find_counterparty(encoded['encodedData']) if match['found']: # Future: x402 payment required before decode real_data = client.decode( continuation_id=encoded['continuationId'], data=match['counterpartyData'], ) return real_data['decodedData']
Explore all endpoints, request/response schemas, and try the API interactively. Open API Reference →