JavaScript SDK Documentation
The Sharokey JavaScript library allows easy integration of secure secret sharing into your JavaScript/TypeScript applications. It reproduces all Sharokey CLI functionality with a modern and intuitive API.
✨ Key Features
- 🔐 Zero Knowledge Encryption: Client-side AES-GCM-256
- 🌍 Multi-environment: Node.js and browsers
- 📱 Modern API: Promises, async/await, TypeScript
- 🔑 Authentication: API Token via Laravel Sanctum
- 📎 File Attachments: Support for encrypted files (max 10 files, 10MB total)
- 🎛️ Advanced Configuration: Retry, timeout, logs
- 🧪 Complete Testing: Coverage and validation
📦 Installation
⚠️ Important Note: This package is not yet available on NPM. This documentation describes the future API based on existing implementation.
NPM (Coming Soon)
# Not yet available
# npm install sharokey-jsYarn (Coming Soon)
# Not yet available
# yarn add sharokey-jsCDN (Browser) - Not Yet Available
<!-- Not yet available -->
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/sharokey.min.js"></script> -->🚀 Quick Start
ES6/TypeScript Import
import { SharokeyClient } from 'sharokey-js';
// or
import SharokeyClient from 'sharokey-js';CommonJS Require
const { SharokeyClient } = require('sharokey-js');Basic Usage
// Client configuration
const client = new SharokeyClient({
token: 'your-api-token',
apiUrl: 'https://api.sharokey.com/api/v1'
});
// Create a secret
const secret = await client.createSecret({
content: "My secret password",
expirationHours: 24,
maximumViews: 1,
description: "Temporary access"
});
console.log('Secret created:', secret.shareUrl);
console.log('Expires on:', secret.expiration);⚙️ Configuration
Basic Configuration
const client = new SharokeyClient({
token: 'your-api-token', // REQUIRED
apiUrl: 'https://api.sharokey.com/api/v1', // Optional
timeout: 30000, // 30 seconds
retries: 3 // 3 retries
});Advanced Configuration
const client = new SharokeyClient({
token: 'your-api-token',
apiUrl: 'https://api.sharokey.com/api/v1',
timeout: 60000,
retries: 5,
defaultExpirationHours: 48,
defaultMaximumViews: 3,
logLevel: 'info', // debug, info, warn, error
validateSsl: true,
headers: {
'X-Custom-Header': 'value'
}
});Configuration Validation
import { validateConfig } from 'sharokey-js';
const errors = validateConfig({
token: 'test',
timeout: -1 // Error
});
if (errors.length > 0) {
console.error('Configuration errors:', errors);
}🔑 Authentication
With API Token
const client = new SharokeyClient({
token: 'sk_live_abcdefghijklmnop1234567890'
});
// Validate token
const userInfo = await client.validateToken();
if (userInfo) {
console.log('Connected as:', userInfo.email);
} else {
console.error('Invalid token');
}Connectivity Test
const isConnected = await client.testConnection();
if (!isConnected) {
throw new Error('Unable to connect to Sharokey API');
}User Information
const user = client.getCurrentUser();
console.log('Current user:', user);📝 Creating Secrets
Simple Creation
const secret = await client.createSecret("My secret");
console.log('Share link:', secret.shareUrl);Creation with Options
const secret = await client.createSecret({
content: "Confidential information",
description: "Important client data",
message: "Please review before tomorrow",
expirationHours: 48,
maximumViews: 3,
password: "additional-protection"
});With File Attachments
import fs from 'fs';
const fileData = fs.readFileSync('document.pdf');
const secret = await client.createSecret({
content: "Here is the requested document",
description: "Confidential contract",
expirationHours: 72,
maximumViews: 1,
attachments: [
{
name: 'contract.pdf',
data: fileData
},
{
name: 'annex.docx',
data: annexData
}
]
});With OTP Protection
const secret = await client.createSecret({
content: "Critical access code",
expirationHours: 1,
maximumViews: 1,
otpEmail: "[email protected]",
// or (mutually exclusive)
otpPhone: "+33123456789"
});Password Generator
// Generate a simple password
const password = client.generatePassword();
console.log('Generated password:', password);
// Generate and create a secret
const result = await client.createPasswordSecret(
"Temporary server access",
{
passwordLength: 20,
includeSymbols: true,
expirationHours: 2,
maximumViews: 1
}
);
console.log('Password:', result.password);
console.log('Link:', result.secret.shareUrl);🛡️ Advanced Security Options
CAPTCHA Protection
// Enable CAPTCHA verification
const secret = await client.createSecret({
content: "Sensitive information",
expirationHours: 2,
maximumViews: 1,
captcha: true,
description: "CAPTCHA protected secret"
});IP Whitelist Restrictions
// Restrict access to specific IPs
const secret = await client.createSecret({
content: "Internal documentation",
expirationHours: 24,
maximumViews: 5,
ipWhitelist: "192.168.1.100,10.0.0.0/24,203.0.113.5", // Max 255 characters
description: "Only accessible from office network"
});Geolocation Restrictions
// Restrict access to specific countries
const secret = await client.createSecret({
content: "Regional configuration data",
expirationHours: 12,
maximumViews: 3,
geolocation: "FR,DE,BE,NL,IT,ES", // Max 255 characters
description: "European Union only access"
});Combined Security (Maximum Protection)
// Use all security features together
const secret = await client.createSecret({
content: "Top secret information",
expirationHours: 1,
maximumViews: 1,
description: "Maximum security secret",
message: "Handle with extreme care - contains sensitive data",
password: "extra-secure-password",
captcha: true,
ipWhitelist: "192.168.1.0/24",
geolocation: "FR,US",
otpEmail: "[email protected]"
});Custom Messages
// Add instructions for recipients
const secret = await client.createSecret({
content: "Monthly report data",
expirationHours: 48,
maximumViews: 10,
description: "Q3 Financial Report",
message: "Please review by Friday and provide feedback via email"
});Builder Pattern
import { createSecretRequest } from 'sharokey-js';
const request = createSecretRequest()
.setContent("Complex secret")
.setDescription("Detailed description")
.setMessage("Instructions for recipient")
.setExpirationHours(24)
.setMaximumViews(5)
.setPassword("password")
.setCaptcha(true)
.setIpWhitelist("192.168.1.0/24,10.0.0.1")
.setGeolocation("FR,US,CA")
.setOtpEmail("[email protected]")
.addAttachment('file1.txt', buffer1)
.addAttachment('file2.pdf', buffer2);
const secret = await client.createSecret(request);📊 Listing and Management
List All Secrets
const result = await client.listSecrets();
console.log(`${result.data.length} secrets found`);
result.data.forEach(secret => {
console.log(`${secret.slug}: ${secret.description} (${secret.currentViews}/${secret.maximumViews})`);
});List with Filters
const secrets = await client.listSecrets({
status: 'active',
creator: '[email protected]',
limit: 10,
search: 'keyword'
});Secret Details
const secret = await client.getSecret('ABC123XY');
console.log('Description:', secret.description);
console.log('Message:', secret.message);
console.log('Creator:', secret.creator);
console.log('Remaining views:', secret.getRemainingViews());
console.log('Expires in:', secret.getTimeRemaining(), 'ms');
console.log('Active:', secret.isActive());
console.log('Has CAPTCHA:', secret.captcha);
console.log('OTP Type:', secret.otpType);
console.log('IP Whitelist:', secret.ipWhitelist);
console.log('Geolocation:', secret.geolocation);Delete Secret
const deleted = await client.deleteSecret('ABC123XY');
if (deleted) {
console.log('Secret deleted successfully');
}Usage Statistics
const stats = await client.getStatistics();
console.log('Statistics:');
console.log('- Total secrets:', stats.totalSecrets);
console.log('- Active secrets:', stats.activeSecrets);
console.log('- Expired secrets:', stats.expiredSecrets);
console.log('- Total views:', stats.totalViews);
console.log('- Secrets with password:', stats.secretsWithPassword);
console.log('- Created today:', stats.secretsCreatedToday);
console.log('- Created this week:', stats.secretsCreatedThisWeek);
console.log('- Created this month:', stats.secretsCreatedThisMonth);🔧 Advanced Features
Secret Search
const secrets = await client.searchSecrets("keyword", {
limit: 20,
status: 'active'
});
console.log(`${secrets.length} secrets found`);Active Secrets Only
const activeSecrets = await client.getActiveSecrets(50);
console.log('Still accessible secrets:', activeSecrets.length);Configuration Update
client.updateConfig({
timeout: 60000,
retries: 5,
logLevel: 'debug'
});
// Chainable
client.updateConfig({ timeout: 30000 })
.updateConfig({ retries: 3 });📖 API Reference
SharokeyClient
Main Methods
createSecret(content, options?)→Promise<Secret>listSecrets(filters?)→Promise<ListResponse<Secret>>getSecret(slug)→Promise<Secret>deleteSecret(slug)→Promise<boolean>getStatistics()→Promise<Statistics>
Utility Methods
generatePassword(length?, symbols?)→stringtestConnection()→Promise<boolean>validateToken()→Promise<Object|null>getCurrentUser()→Object|nullgetInfo()→ClientInfo
Advanced Methods
createPasswordSecret(desc, options?)→Promise<{secret, password}>searchSecrets(query, options?)→Promise<Secret[]>getActiveSecrets(limit?)→Promise<Secret[]>
Secret Request Methods
createSecretRequest(options?)→Promise<SecretRequest>listSecretRequests(filters?)→Promise<ListResponse<SecretRequest>>getSecretRequest(id)→Promise<SecretRequest>deleteSecretRequest(id)→Promise<boolean>getSecretRequestStatistics()→Promise<Object>getActiveSecretRequests(limit?)→Promise<SecretRequest[]>
Secret
Properties
slug: string- Unique identifierdescription: string- Descriptioncreator: string- Creator emailmaximumViews: number- Maximum viewscurrentViews: number- Current viewsexpiration: Date- Expiration datehasAttachments: boolean- Has attachmentsattachmentsCount: number- Number of attachmentsshareUrl: string- Complete share URL
Methods
isActive()→booleangetRemainingViews()→numbergetTimeRemaining()→number|null
Statistics
Properties
totalSecrets: number- Total secretsactiveSecrets: number- Active secretsexpiredSecrets: number- Expired secretstotalViews: number- Total viewssecretsWithPassword: number- Secrets with password protectionsecretsCreatedToday: number- Created todaysecretsCreatedThisWeek: number- Created this weeksecretsCreatedThisMonth: number- Created this month
SecretRequest
Properties
id: number- Unique identifiertoken: string- Request tokenmessage: string- Message for recipientdescription: string- Internal descriptionsecretExpirationHours: number- Hours until secret expiresrequestExpirationHours: number- Hours until request expiresmaximumViews: number- Maximum views for secretemailTo: string- Recipient emailemailReply: string- Reply-to emailcreator: string- Creator emailstatus: string- Request status (active, expired)url: string- Request share URLcreatedAt: Date- Creation date
Methods
isActive()→booleanisExpired()→booleangetShareUrl()→string
💡 Practical Examples
Web Application for Sharing
class SecretManager {
constructor(token) {
this.client = new SharokeyClient({ token });
}
async sharePassword(password, recipient) {
const secret = await this.client.createSecret({
content: password,
description: `Password for ${recipient}`,
expirationHours: 1,
maximumViews: 1,
otpEmail: recipient
});
return secret.shareUrl;
}
async shareDocument(filePath, description) {
const fs = require('fs');
const fileData = fs.readFileSync(filePath);
const secret = await this.client.createSecret({
content: "Confidential document attached",
description: description,
expirationHours: 48,
maximumViews: 3,
attachments: [{
name: path.basename(filePath),
data: fileData
}]
});
return secret.shareUrl;
}
async requestCredentials(email, description) {
const request = await this.client.createSecretRequest({
message: "Please share the requested credentials securely",
description: description,
secretExpirationHours: 24,
requestExpirationHours: 48,
maximumViews: 1,
emailTo: email,
emailReply: "[email protected]"
});
return request.url;
}
async getDashboard() {
const [stats, activeSecrets, activeRequests] = await Promise.all([
this.client.getStatistics(),
this.client.getActiveSecrets(10),
this.client.getActiveSecretRequests(5)
]);
return { stats, activeSecrets, activeRequests };
}
}Express.js Integration
const express = require('express');
const { SharokeyClient } = require('sharokey-js');
const app = express();
const client = new SharokeyClient({
token: process.env.SHAROKEY_TOKEN
});
app.use(express.json());
// Create secret via REST API
app.post('/api/secrets', async (req, res) => {
try {
const { content, description, hours, views } = req.body;
const secret = await client.createSecret({
content,
description,
expirationHours: hours || 24,
maximumViews: views || 1
});
res.json({
success: true,
shareUrl: secret.shareUrl,
expiresAt: secret.expiration
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
// List secrets
app.get('/api/secrets', async (req, res) => {
try {
const result = await client.listSecrets({
limit: parseInt(req.query.limit) || 50
});
res.json({
success: true,
secrets: result.data,
pagination: result.meta
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
app.listen(3000, () => {
console.log('API started on http://localhost:3000');
});React Hook Usage
import { useState, useEffect } from 'react';
import { SharokeyClient } from 'sharokey-js';
function useSharokey(token) {
const [client] = useState(() => new SharokeyClient({ token }));
const [secrets, setSecrets] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const createSecret = async (content, options) => {
setLoading(true);
try {
const secret = await client.createSecret(content, options);
setSecrets(prev => [secret, ...prev]);
return secret;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
};
const refreshSecrets = async () => {
setLoading(true);
try {
const result = await client.listSecrets();
setSecrets(result.data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
useEffect(() => {
refreshSecrets();
}, []);
return {
secrets,
loading,
error,
createSecret,
refreshSecrets,
client
};
}
// Usage in a component
function SecretManager() {
const { secrets, createSecret, loading } = useSharokey(process.env.REACT_APP_SHAROKEY_TOKEN);
const handleCreate = async () => {
await createSecret("My new secret", {
expirationHours: 24,
maximumViews: 1
});
};
return (
<div>
<button onClick={handleCreate} disabled={loading}>
Create Secret
</button>
<ul>
{secrets.map(secret => (
<li key={secret.slug}>
{secret.description} - {secret.getRemainingViews()} views remaining
</li>
))}
</ul>
</div>
);
}🚨 Error Handling
Error Types
import { ApiError } from 'sharokey-js';
try {
await client.createSecret("test");
} catch (error) {
if (error instanceof ApiError) {
switch (error.status) {
case 401:
console.error('Invalid or expired token');
break;
case 403:
console.error('Access denied');
break;
case 429:
console.error('Rate limit reached');
break;
case 500:
console.error('Server error:', error.message);
break;
default:
console.error(`API error ${error.status}:`, error.message);
}
} else {
console.error('Local error:', error.message);
}
}Local Validation
try {
const secret = await client.createSecret({
content: "", // Validation error
expirationHours: -1 // Validation error
});
} catch (error) {
console.error('Validation error:', error.message);
// "Validation errors: Content is required, Expiration hours must be between 1 and 1000"
}Automatic Retry
// Network errors are automatically retried
const client = new SharokeyClient({
token: 'test',
retries: 5, // Maximum 5 attempts
timeout: 60000 // 60 seconds
});
// 4xx errors are NOT retried (client errors)
// 5xx errors ARE retried (server errors)🎛️ Advanced Configuration
Environment Variables
# .env
SHAROKEY_TOKEN=sk_live_abcdefghijklmnop1234567890
SHAROKEY_API_URL=https://api.sharokey.com/api/v1
SHAROKEY_TIMEOUT=60000
SHAROKEY_LOG_LEVEL=infoconst client = new SharokeyClient({
token: process.env.SHAROKEY_TOKEN,
apiUrl: process.env.SHAROKEY_API_URL,
timeout: parseInt(process.env.SHAROKEY_TIMEOUT) || 30000,
logLevel: process.env.SHAROKEY_LOG_LEVEL || 'info'
});Environment-based Configuration
const configs = {
development: {
apiUrl: 'https://dev.api.sharokey.com/api/v1',
logLevel: 'debug',
validateSsl: false
},
staging: {
apiUrl: 'https://staging.api.sharokey.com/api/v1',
logLevel: 'info'
},
production: {
apiUrl: 'https://api.sharokey.com/api/v1',
logLevel: 'warn',
retries: 5
}
};
const client = new SharokeyClient({
token: process.env.SHAROKEY_TOKEN,
...configs[process.env.NODE_ENV || 'development']
});Custom Logging
// The library logs automatically based on configured level
// debug: Detailed requests
// info: Important operations
// warn: Non-critical problems
// error: Critical errors
const client = new SharokeyClient({
token: 'test',
logLevel: 'debug' // See all HTTP requests
});💬 Support
Technical Documentation
- REST API : https://api.sharokey.com/docs
- CLI : Sharokey CLI Documentation
- Outlook : Outlook Add-in Guide
Resources
- GitHub : https://github.com/sharokey/sharokey-js
- NPM : https://www.npmjs.com/package/sharokey-js
- Changelog : Version history
Contact
- Technical Support : [email protected]
- Bugs and Features : GitHub Issues
- Documentation : [email protected]
FAQ
Q: Does the library work in browsers?
A: Yes, it works in all modern browsers supporting the Web Crypto API (Chrome 37+, Firefox 34+, Safari 7+).
Q: Can I use enterprise tokens?
A: Yes, all Sharokey API token types are supported (user and enterprise).
Q: Are secrets really encrypted client-side?
A: Yes, AES-GCM-256 encryption is performed entirely client-side. The server only receives encrypted data.
Q: What's the maximum file size?
A: 10MB total for all files combined, 10 files maximum per secret.
Q: Does the library support TypeScript?
A: Yes, TypeScript definitions are included in the package.
Documentation generated 08/01/2025 - Sharokey Team
