@ciphyrshq/sdk
v2.6.0
Published
Official JavaScript / TypeScript SDK for the Ciphyrs PII Shield API
Maintainers
Readme
@ciphyrshq/sdk
Official JavaScript/TypeScript SDK for the Ciphyrs PII Shield API. Mask and restore sensitive data (PII) in LLM prompts with a single function call.
Installation
npm install @ciphyrshq/sdkRequires Node.js 18+ (uses native fetch).
Quick Start
import { CiphyrsClient } from '@ciphyrshq/sdk'
const client = new CiphyrsClient({ apiKey: 'cyp_live_...' })
// Mask PII before sending to an LLM
const { maskedText, sessionId } = await client.mask(
'Contact John at [email protected] or +91-9876543210'
)
// => "Contact [PERSON_1] at [EMAIL_ADDRESS_1] or [PHONE_NUMBER_1]"
// After getting the LLM response, restore original values
const { restoredText } = await client.restore(maskedResponse, sessionId)One-Shot Protect (recommended)
protect() wraps mask → LLM call → restore in a single call so you
can't accidentally ship [PERSON_1] to your end users:
const result = await client.scan.protect(userMessage, async (masked) => {
const r = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: masked }],
})
return r.choices[0].message.content
})
res.send(result.output) // "Hello John, ..." — never "[PERSON_1]"Active Blocking with the Guard (V58)
Block prompt-injection / jailbreak / PII-leak attempts inline before they reach your LLM. <50ms p95 latency, 5 detection layers (regex, threat-intel, multilingual, custom rules, canaries):
// Option 1 — manual check
const guard = await client.guard.check({
input: userMessage,
agentName: 'support-bot',
userId: req.user.id,
})
if (guard.decision === 'block') {
return res.status(400).send({ error: guard.reason })
}
// Option 2 — wrap the whole LLM call
const result = await client.guard.wrap(userMessage, async (input) => {
return (await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: input }],
})).choices[0].message.content
})
if (result.blocked) return res.status(400).send({ error: result.reason })
res.send(result.output)Security Operations (V55-V59)
// List recent attack detections
const { detections } = await client.security.listDetections({ days: 7, severity: 'high' })
// Create a honeypot canary token (zero-FP exfiltration alarm)
const { canary, token } = await client.security.createCanary({
name: 'fake admin api key',
scope: 'output',
})
// → save `token` and plant it in test data; if it ever appears in prod
// output you get an instant critical alert.
// Generate an SOC 2 / compliance prod report
const { report } = await client.reports.generateProd({
title: 'Q4 2026 SOC 2 Evidence',
rangeStart: '2026-10-01',
rangeEnd: '2026-12-31',
sections: ['security_incidents', 'pii_detections', 'performance', 'cost'],
})
const pdf = await client.reports.downloadProdPdf(report.id)
fs.writeFileSync('soc2-evidence.pdf', pdf)
// Share with auditors (no Ciphyrs login required)
const { share_url_path } = await client.reports.share(report.id, 30)Async Scanning
For large texts or batch workflows, use async scanning:
const { jobId, sessionId } = await client.maskAsync(longDocument, {
source: 'RAG',
surface: 'api',
})
// Poll until complete (auto-polls every 500ms)
const result = await client.waitForJob(jobId, { timeoutMs: 30_000 })
console.log(result.maskedText)API Key Management
// Requires JWT token (dashboard auth)
const client = new CiphyrsClient({ token: jwtToken })
const { apiKey, key } = await client.createKey({ name: 'Production', scopes: ['scan'] })
const { apiKeys } = await client.auth.listApiKeys()
await client.auth.revokeApiKey(key.id)Dashboard Metrics
const client = new CiphyrsClient({ token: jwtToken })
const summary = await client.metrics.summary()
const ts = await client.metrics.timeseries({ range: '30d' })
const entities = await client.metrics.byEntity()
const latency = await client.metrics.latencyPercentiles()
const heatmap = await client.metrics.peakHours()
const report = await client.metrics.complianceReport({ from: '2026-01-01', to: '2026-03-31' })Configuration
| Option | Default | Description |
|-----------|----------------------------|--------------------------------------|
| apiKey | - | API key (cyp_live_...) for scans |
| token | - | JWT for dashboard/management APIs |
| baseUrl | https://www.ciphyrs.com | Gateway URL (VPC/on-prem override) |
| dashUrl | https://www.ciphyrs.com | Dashboard API URL |
| timeout | 10000 | Request timeout in ms |
Error Handling
All errors extend CiphyrsError:
import { CiphyrsRateLimitError, CiphyrsAuthError } from '@ciphyrshq/sdk'
try {
await client.mask(text)
} catch (err) {
if (err instanceof CiphyrsRateLimitError) {
// err.retryAfter — seconds until retry is safe
}
if (err instanceof CiphyrsAuthError) {
// Invalid or expired API key / token
}
}| Error Class | HTTP Status | When |
|--------------------------|-------------|---------------------------------|
| CiphyrsAuthError | 401 | Invalid/expired credentials |
| CiphyrsPermissionError| 403 | Insufficient role/scopes |
| CiphyrsNotFoundError | 404 | Resource not found |
| CiphyrsRateLimitError | 429 | Rate limit exceeded |
| CiphyrsTimeoutError | - | Request timed out |
| CiphyrsJobTimeoutError| - | Async job polling timed out |
Auto-Retry
The SDK automatically retries on transient errors (429, 500, 502, 503, 504) with exponential backoff. Up to 3 retries with a 500ms base delay. Respects Retry-After headers.
TypeScript
Full type definitions included via types.d.ts. Import types directly:
import type { MaskResult, RestoreResult, CiphyrsClientOptions } from '@ciphyrshq/sdk'License
MIT
