Repository navigation
Developer API
The Byhun Developer API allows web-based apps to interact with the file system and system information in a secure, sandboxed environment. All file operations are restricted to an isolated directory specific to your app, ensuring security and preventing malicious access to the user's system.
- ✅ Secure file operations (read, write, delete, move)
- ✅ File listing and information
- ✅ System information access
- ✅ Complete sandbox isolation
- ✅ Async/await Promise-based API
- Developer API must be enabled in Byhun settings (disabled by default)
- Your app must be loaded in Byhun WebView
- All file operations are automatically restricted to your app's sandbox
Before using the API, users must enable it in Byhun settings:
- Open Byhun app
- Go to Settings
- Scroll to Developer API section
- Toggle Enable Developer API ON
- Save settings
Always check if the API is available and enabled before using it:
// Check if API is available
if (typeof window.byhunAPI === 'undefined') {
console.error('Byhun API is not available');
alert('Please enable Developer API in Byhun settings');
return;
}
// Check if API is enabled
if (!window.byhunAPI.enabled) {
console.error('Byhun API is disabled');
alert('Please enable Developer API in Byhun settings');
return;
}
console.log('API ready! App ID:', window.byhunAPI.appId);All API methods return Promises, so use async/await or .then():
// Using async/await (recommended)
async function example() {
try {
const info = await window.byhunAPI.getSystemInfo();
console.log('Platform:', info.platform);
console.log('Version:', info.version);
} catch (error) {
console.error('Error:', error);
}
}
// Using .then()
window.byhunAPI.getSystemInfo()
.then(info => {
console.log('System info:', info);
})
.catch(error => {
console.error('Error:', error);
});Returns information about the system running Byhun.
Returns: Promise<Object>
Response:
{
success: true,
platform: "windows" | "android" | "linux" | "macos",
version: "10.0.26100", // OS version string
sandboxEnabled: true
}Example:
async function getSystemInfo() {
try {
const info = await window.byhunAPI.getSystemInfo();
console.log(`Running on ${info.platform} ${info.version}`);
return info;
} catch (error) {
console.error('Failed to get system info:', error);
}
}All file paths are relative to your app's sandbox directory. You cannot access files outside the sandbox.
Reads a file from the sandbox and returns its content as a string.
Parameters:
-
path(string): Relative path to the file (e.g.,"data/config.json")
Returns: Promise<string> - File content as string
Example:
async function loadConfig() {
try {
const content = await window.byhunAPI.readFile('config.json');
const config = JSON.parse(content);
console.log('Config loaded:', config);
return config;
} catch (error) {
console.error('Failed to read config:', error);
// Return default config
return { theme: 'dark', lang: 'en' };
}
}Writes content to a file in the sandbox. Creates parent directories if they don't exist.
Parameters:
-
path(string): Relative path to the file (e.g.,"data/save.json") -
content(string): Content to write to the file
Returns: Promise<Object>
Response:
{
success: true,
message: "File written successfully"
}Example:
async function saveGame(saveData) {
try {
const content = JSON.stringify(saveData, null, 2);
await window.byhunAPI.writeFile('saves/game1.json', content);
console.log('Game saved successfully!');
} catch (error) {
console.error('Failed to save game:', error);
alert('Failed to save game. Please try again.');
}
}
// Save user preferences
async function savePreferences(prefs) {
await window.byhunAPI.writeFile('preferences.json', JSON.stringify(prefs));
}Deletes a file from the sandbox.
Parameters:
-
path(string): Relative path to the file to delete
Returns: Promise<Object>
Response:
{
success: true,
message: "File deleted successfully"
}Example:
async function deleteSave(saveName) {
try {
await window.byhunAPI.deleteFile(`saves/${saveName}.json`);
console.log('Save file deleted');
} catch (error) {
console.error('Failed to delete save:', error);
}
}Moves (renames) a file from source path to destination path.
Parameters:
-
sourcePath(string): Current file path -
destPath(string): New file path
Returns: Promise<Object>
Response:
{
success: true,
message: "File moved successfully"
}Example:
async function renameSave(oldName, newName) {
try {
await window.byhunAPI.moveFile(
`saves/${oldName}.json`,
`saves/${newName}.json`
);
console.log('Save renamed');
} catch (error) {
console.error('Failed to rename save:', error);
}
}Lists all files in a directory.
Parameters:
-
directoryPath(string, optional): Directory path. If not provided, lists root sandbox directory.
Returns: Promise<string[]> - Array of file paths
Example:
async function listSaves() {
try {
const files = await window.byhunAPI.listFiles('saves');
console.log('Save files:', files);
// Returns: ['game1.json', 'game2.json', ...]
return files;
} catch (error) {
console.error('Failed to list saves:', error);
return [];
}
}
// List all files in sandbox root
async function listAllFiles() {
const files = await window.byhunAPI.listFiles();
console.log('All files:', files);
}Checks if a file exists in the sandbox.
Parameters:
-
path(string): File path to check
Returns: Promise<boolean> - true if file exists, false otherwise
Example:
async function checkSaveExists(saveName) {
const exists = await window.byhunAPI.fileExists(`saves/${saveName}.json`);
if (exists) {
console.log('Save file exists');
} else {
console.log('Save file does not exist');
}
return exists;
}Gets detailed information about a file.
Parameters:
-
path(string): File path
Returns: Promise<Object>
Response:
{
success: true,
path: "data/config.json",
size: 1024, // File size in bytes
modified: "2024-01-15T10:30:00.000Z", // ISO 8601 timestamp
isFile: true,
isDirectory: false
}Example:
async function getFileDetails(path) {
try {
const info = await window.byhunAPI.getFileInfo(path);
console.log('File size:', info.size, 'bytes');
console.log('Last modified:', new Date(info.modified));
return info;
} catch (error) {
console.error('Failed to get file info:', error);
}
}All API methods can throw errors. Always use try-catch blocks:
async function safeFileOperation() {
try {
const content = await window.byhunAPI.readFile('data.json');
// Process content
} catch (error) {
// Handle different error types
if (error.message.includes('File not found')) {
console.log('File does not exist, creating default...');
await window.byhunAPI.writeFile('data.json', '{}');
} else if (error.message.includes('SecurityException')) {
console.error('Security violation!', error);
alert('Invalid file path. Please contact app developer.');
} else {
console.error('Unexpected error:', error);
alert('An error occurred. Please try again.');
}
}
}-
"API is disabled"- Developer API is not enabled in settings -
"API bridge not available"- API is not initialized -
"File not found"- Requested file doesn't exist -
"SecurityException: Path outside sandbox"- Attempted to access files outside sandbox -
"App ID mismatch"- Internal security error (should not occur)
Each app has its own isolated sandbox directory. Files cannot escape this directory, and apps cannot access files from other apps or the user's system.
-
Allowed: Relative paths like
"data/file.json","saves/game1.json" -
Blocked: Absolute paths like
"C:/Users/..."or"/etc/passwd" -
Blocked: Path traversal attempts like
"../../../etc/passwd"
All path traversal attempts (e.g., ../, ..\\) are automatically removed for security.
- Always validate paths before using them
- Never trust user input without sanitization
-
Use subdirectories to organize files (e.g.,
saves/,data/,cache/) - Handle errors gracefully and inform users
class GameSaveManager {
constructor() {
this.saveDir = 'saves';
}
async saveGame(slotId, gameData) {
try {
const filename = `${this.saveDir}/slot${slotId}.json`;
const content = JSON.stringify({
...gameData,
savedAt: new Date().toISOString(),
version: '1.0.0'
}, null, 2);
await window.byhunAPI.writeFile(filename, content);
console.log(`Game saved to slot ${slotId}`);
return true;
} catch (error) {
console.error('Save failed:', error);
return false;
}
}
async loadGame(slotId) {
try {
const filename = `${this.saveDir}/slot${slotId}.json`;
const exists = await window.byhunAPI.fileExists(filename);
if (!exists) {
return null; // No save file
}
const content = await window.byhunAPI.readFile(filename);
return JSON.parse(content);
} catch (error) {
console.error('Load failed:', error);
return null;
}
}
async listSaves() {
try {
// Ensure saves directory exists
const files = await window.byhunAPI.listFiles(this.saveDir);
return files.filter(f => f.endsWith('.json'));
} catch (error) {
// Directory might not exist yet
return [];
}
}
async deleteSave(slotId) {
try {
await window.byhunAPI.deleteFile(`${this.saveDir}/slot${slotId}.json`);
return true;
} catch (error) {
console.error('Delete failed:', error);
return false;
}
}
}
// Usage
const saveManager = new GameSaveManager();
// Save game
await saveManager.saveGame(1, {
level: 5,
score: 1000,
playerName: 'Player1'
});
// Load game
const gameData = await saveManager.loadGame(1);
if (gameData) {
console.log('Loaded:', gameData);
}
// List all saves
const saves = await saveManager.listSaves();
console.log('Available saves:', saves);class ConfigManager {
constructor(configPath = 'config.json') {
this.configPath = configPath;
this.defaultConfig = {
theme: 'dark',
language: 'en',
volume: 0.7,
notifications: true
};
}
async loadConfig() {
try {
const exists = await window.byhunAPI.fileExists(this.configPath);
if (!exists) {
// Create default config
await this.saveConfig(this.defaultConfig);
return { ...this.defaultConfig };
}
const content = await window.byhunAPI.readFile(this.configPath);
const config = JSON.parse(content);
// Merge with defaults to ensure all keys exist
return { ...this.defaultConfig, ...config };
} catch (error) {
console.error('Failed to load config:', error);
return { ...this.defaultConfig };
}
}
async saveConfig(config) {
try {
const content = JSON.stringify(config, null, 2);
await window.byhunAPI.writeFile(this.configPath, content);
return true;
} catch (error) {
console.error('Failed to save config:', error);
return false;
}
}
async updateConfig(key, value) {
const config = await this.loadConfig();
config[key] = value;
return await this.saveConfig(config);
}
}
// Usage
const configManager = new ConfigManager();
// Load configuration
const config = await configManager.loadConfig();
console.log('Current theme:', config.theme);
// Update a setting
await configManager.updateConfig('theme', 'light');
// Save full config
await configManager.saveConfig({
theme: 'light',
language: 'pt',
volume: 0.8,
notifications: false
});class CacheManager {
constructor(cacheDir = 'cache') {
this.cacheDir = cacheDir;
this.maxCacheSize = 50 * 1024 * 1024; // 50 MB
}
async getCacheKey(key) {
const filename = `${this.cacheDir}/${key}.cache`;
const exists = await window.byhunAPI.fileExists(filename);
if (!exists) {
return null;
}
try {
const info = await window.byhunAPI.getFileInfo(filename);
const age = Date.now() - new Date(info.modified).getTime();
const maxAge = 7 * 24 * 60 * 60 * 1000; // 7 days
if (age > maxAge) {
// Cache expired
await window.byhunAPI.deleteFile(filename);
return null;
}
const content = await window.byhunAPI.readFile(filename);
return JSON.parse(content);
} catch (error) {
console.error('Cache read error:', error);
return null;
}
}
async setCacheKey(key, data) {
const filename = `${this.cacheDir}/${key}.cache`;
try {
const content = JSON.stringify({
data,
cachedAt: new Date().toISOString()
});
await window.byhunAPI.writeFile(filename, content);
return true;
} catch (error) {
console.error('Cache write error:', error);
return false;
}
}
async clearCache() {
try {
const files = await window.byhunAPI.listFiles(this.cacheDir);
for (const file of files) {
await window.byhunAPI.deleteFile(`${this.cacheDir}/${file}`);
}
return true;
} catch (error) {
console.error('Cache clear error:', error);
return false;
}
}
async getCacheSize() {
try {
const files = await window.byhunAPI.listFiles(this.cacheDir);
let totalSize = 0;
for (const file of files) {
const info = await window.byhunAPI.getFileInfo(`${this.cacheDir}/${file}`);
totalSize += info.size;
}
return totalSize;
} catch (error) {
return 0;
}
}
}
// Usage
const cache = new CacheManager();
// Cache data
await cache.setCacheKey('userData', { name: 'John', id: 123 });
// Retrieve from cache
const userData = await cache.getCacheKey('userData');
if (userData) {
console.log('From cache:', userData);
} else {
console.log('Cache miss, fetching...');
// Fetch from server...
}
// Clear old cache
const size = await cache.getCacheSize();
if (size > cache.maxCacheSize) {
await cache.clearCache();
}async function displaySystemInfo() {
try {
const info = await window.byhunAPI.getSystemInfo();
const infoDiv = document.getElementById('system-info');
infoDiv.innerHTML = `
<h3>System Information</h3>
<p><strong>Platform:</strong> ${info.platform}</p>
<p><strong>Version:</strong> ${info.version}</p>
<p><strong>Sandbox:</strong> ${info.sandboxEnabled ? 'Enabled' : 'Disabled'}</p>
`;
} catch (error) {
console.error('Failed to get system info:', error);
}
}
// Call on page load
window.addEventListener('DOMContentLoaded', displaySystemInfo);function checkAPI() {
if (typeof window.byhunAPI === 'undefined' || !window.byhunAPI.enabled) {
alert('Developer API is not enabled. Please enable it in Byhun settings.');
return false;
}
return true;
}
if (!checkAPI()) {
// Fallback behavior
console.warn('Using fallback storage (localStorage)');
}// ✅ Good
async function loadData() {
try {
const data = await window.byhunAPI.readFile('data.json');
return JSON.parse(data);
} catch (error) {
console.error(error);
return null;
}
}
// ❌ Avoid deeply nested promises
function loadData() {
window.byhunAPI.readFile('data.json')
.then(data => {
JSON.parse(data)
.then(result => {
// Process result
})
.catch(error => {
// Handle error
});
})
.catch(error => {
// Handle error
});
}// ✅ Good - organized structure
await window.byhunAPI.writeFile('saves/game1.json', data);
await window.byhunAPI.writeFile('config/settings.json', config);
await window.byhunAPI.writeFile('cache/data.cache', cache);
// ❌ Avoid - flat structure
await window.byhunAPI.writeFile('game1.json', data);
await window.byhunAPI.writeFile('settings.json', config);
await window.byhunAPI.writeFile('data.cache', cache);async function safeOperation(path) {
try {
return await window.byhunAPI.readFile(path);
} catch (error) {
if (error.message.includes('not found')) {
// File doesn't exist - not necessarily an error
return null;
} else {
// Real error - log and handle
console.error('Operation failed:', error);
showErrorToUser('An error occurred. Please try again.');
return null;
}
}
}function sanitizePath(userInput) {
// Remove dangerous characters and path traversal
return userInput
.replace(/[<>:"|?*]/g, '') // Remove invalid characters
.replace(/\.\./g, '') // Remove path traversal
.replace(/^\/+/, ''); // Remove leading slashes
}
async function saveUserFile(userInput, content) {
const safePath = sanitizePath(userInput);
if (!safePath) {
throw new Error('Invalid file name');
}
await window.byhunAPI.writeFile(`user-files/${safePath}`, content);
}Create reusable helper classes for common operations (see examples above) to keep your code clean and maintainable.
Problem: window.byhunAPI is undefined
Solutions:
- Ensure the app is running in Byhun WebView (not in a regular browser)
- Check that Developer API is enabled in Byhun settings
- Verify the page has loaded completely before accessing the API
Problem: File not found errors when files should exist
Solutions:
- Check file paths - they are case-sensitive
- Ensure files are being created before trying to read them
- Use
fileExists()to check before reading
Problem: Security exceptions or permission errors
Solutions:
- Ensure paths are relative (not absolute)
- Avoid path traversal sequences (
../,..\\) - Verify Developer API is enabled
- Check that App ID matches (should happen automatically)
For issues or questions about the Developer API:
- Check this documentation first
- Review error messages carefully
- Ensure Developer API is enabled in settings
- Verify your code follows security best practices
-
v1.0.0 (Current) - Initial API release
- System information
- File operations (read, write, delete, move)
- File listing and information
- Sandbox security
Happy Coding! 🚀