Mini-App API Documentation

Native APIs for mini-apps on Android, Desktop, and AtlayoNET

Overview: Mini-apps access device capabilities through AtlayoInterface. UI components via Atlayo.UI.

Getting Started

Mini-apps run in a sandboxed WebView and access native features through the AtlayoInterface bridge.

Overview: All native APIs are exposed via AtlayoInterface in JavaScript. The bridge is injected automatically when your mini-app loads.
if (typeof AtlayoInterface !== 'undefined') {
    // API is available
    const info = JSON.parse(AtlayoInterface.getSystemInfo());
    console.log('Platform:', info.platform);
}
Tip: Always guard API calls with an availability check, especially for Android-only methods like openCamera().

Storage API

Persistent key-value storage isolated per mini-app. Data persists across sessions via Android SharedPreferences.

setStorage

async
AtlayoInterface.setStorage(storageJson)

Store a value in persistent mini-app storage.

NameTypeDescriptionRequired
storageJsonString (JSON)Object with key (String), data (Any), optional callback (String)Yes
Input
{
  "key": "user_preference",
  "data": { "theme": "dark", "language": "en" },
  "callback": "onStorageSet"
}
Output / Response
{
  "action": "setStorage",
  "key": "user_preference",
  "success": true
}
const request = { key: "user_preference", data: { theme: "dark" }, callback: "onStorageSet" };
AtlayoInterface.setStorage(JSON.stringify(request));

function onStorageSet(response) {
    console.log('Saved:', response.success);
}

getStorage

async
AtlayoInterface.getStorage(requestJson)

Retrieve a value from persistent storage.

NameTypeDescriptionRequired
requestJsonString (JSON)Object with key (String), optional callback (String)Yes
Input
{ "key": "user_preference", "callback": "onStorageGet" }
Output / Response
{
  "action": "getStorage",
  "key": "user_preference",
  "found": true,
  "data": "{\"theme\":\"dark\"}"
}
AtlayoInterface.getStorage(JSON.stringify({ key: "user_preference" }));

function onStorageGet(response) {
    if (response.found) {
        const data = JSON.parse(response.data);
        console.log('Theme:', data.theme);
    }
}

removeStorage

async
AtlayoInterface.removeStorage(requestJson)

Remove a specific key from storage.

NameTypeDescriptionRequired
requestJsonString (JSON)Object with key (String), optional callbackYes
Input
{ "key": "user_preference" }
Output / Response
{
  "action": "removeStorage",
  "key": "user_preference",
  "removed": true
}
AtlayoInterface.removeStorage(JSON.stringify({ key: "user_preference" }));

clearStorage

async
AtlayoInterface.clearStorage(requestJson)

Clear all data from the mini-app storage.

NameTypeDescriptionRequired
requestJsonString (JSON)Empty object {} or object with optional callbackYes
Input
{}
Output / Response
{ "action": "clearStorage", "cleared": true }
AtlayoInterface.clearStorage(JSON.stringify({}));
Errors: Storage failures invoke window.onStorageError(error).

Permissions API

Request access to user data stored in the main Atlayo app. Users must grant permission before data is shared.

requestPermissions

async
AtlayoInterface.requestPermissions(permissionsJson)

Request permission for specific user data fields. Previously granted permissions return data immediately without a dialog.

NameTypeDescriptionRequired
permissionsJsonString (JSON array)Array of permission keys: given_name, family_name, phone_number, notifications, gps, token, bluetoothYes
Input
["given_name", "family_name", "phone_number"]
Output / Response
{
  "given_name": "John",
  "family_name": "Doe",
  "phone_number": "+1234567890"
}
const permissions = ["given_name", "family_name", "phone_number"];
AtlayoInterface.requestPermissions(JSON.stringify(permissions));

window.onPermissionsGranted = function(data) {
    document.getElementById('userName').textContent =
        data.given_name + ' ' + data.family_name;
    const sysInfo = JSON.parse(AtlayoInterface.getSystemInfo());
    if (sysInfo.token) {
        fetch('/api/user-data', {
            headers: { 'Authorization': 'Bearer ' + sysInfo.token }
        });
    }
};
Auto-provided: theme_color, lang, and token are available via getSystemInfo() without requesting.

checkPermissions

async
AtlayoInterface.checkPermissions(permissionsJson)

Check if specific permissions have been granted without showing a dialog.

NameTypeDescriptionRequired
permissionsJsonString (JSON array)Array of permission keysYes
Input
["gps", "bluetooth"]
Output / Response
{
  "gps": true,
  "bluetooth": false
}
AtlayoInterface.checkPermissions(JSON.stringify(["gps", "bluetooth"]));

window.onPermissionsChecked = function(data) {
    console.log("GPS granted:", data.gps);
};

requestAdditionalPermissions

async
AtlayoInterface.requestAdditionalPermissions(permissionsJson)

Request new permissions to be merged with already granted ones. Shows a dialog only if there are new or previously denied permissions.

NameTypeDescriptionRequired
permissionsJsonString (JSON array)Array of permission keysYes
Input
["bluetooth"]
Output / Response
{
  "given_name": "John",
  "bluetooth": true
}
AtlayoInterface.requestAdditionalPermissions(JSON.stringify(["bluetooth"]));

window.onPermissionsGranted = function(data) {
    // Same callback as requestPermissions
};

UI & System API

Customize system UI appearance and retrieve device information.

setStatusBarColor

syncAndroid only
AtlayoInterface.setStatusBarColor(color)

Set the Android status bar color.

NameTypeDescriptionRequired
colorStringHex color, e.g. "#FF0000"Yes
Input
"#FF0000"
Output / Response
void
AtlayoInterface.setStatusBarColor("#FF0000");

setTopBarBackgroundColor

syncAndroid only
AtlayoInterface.setTopBarBackgroundColor(color)

Set the mini-app top bar background color.

NameTypeDescriptionRequired
colorStringHex colorYes
Input
"#3498db"
Output / Response
void
AtlayoInterface.setTopBarBackgroundColor("#3498db");

setTopBarForegroundColor

syncAndroid only
AtlayoInterface.setTopBarForegroundColor(color)

Set the mini-app top bar text/icon color.

NameTypeDescriptionRequired
colorStringHex colorYes
Input
"#FFFFFF"
Output / Response
void
AtlayoInterface.setTopBarForegroundColor("#FFFFFF");

setNavigationBarColor

syncAndroid only
AtlayoInterface.setNavigationBarColor(color, lightNavigationBar)

Set the Android navigation bar color and icon style.

NameTypeDescriptionRequired
colorStringHex colorYes
lightNavigationBarBooleantrue = light icons (dark bg), false = dark iconsYes
Input
AtlayoInterface.setNavigationBarColor("#000000", true)
Output / Response
void
AtlayoInterface.setNavigationBarColor("#000000", true);

setOrientation

syncAndroid only
AtlayoInterface.setOrientation(orientation)

Control the screen orientation (rotation) for the mini-app. By default, the orientation is locked to portrait.

NameTypeDescriptionRequired
orientationString"portrait", "landscape", "auto" (or "sensor"), "locked"Yes
Input
"landscape"
Output / Response
void
AtlayoInterface.setOrientation("landscape");

getSystemInfo

sync
AtlayoInterface.getSystemInfo()

Returns comprehensive device and system information as a JSON string (synchronous).

Input
AtlayoInterface.getSystemInfo()
Output / Response
{
  "brand": "samsung", "model": "SM-G991B", "platform": "android",
  "screenWidth": 1080, "screenHeight": 2400, "darkMode": false,
  "language": "en", "token": "", "safeArea": { "top": 28, "bottom": 0 }
}
const systemInfo = JSON.parse(AtlayoInterface.getSystemInfo());
document.getElementById('deviceInfo').textContent =
    systemInfo.brand + ' ' + systemInfo.model;
document.getElementById('screenSize').textContent =
    systemInfo.screenWidth + ' x ' + systemInfo.screenHeight;
if (systemInfo.darkMode) document.body.classList.add('dark-mode');
const safeArea = systemInfo.safeArea;
document.getElementById('content').style.paddingTop = safeArea.top + 'px';
PropertyTypeDescription
brandStringDevice manufacturer (e.g. "samsung", "google")
modelStringDevice model name
pixelRatioNumberDevice pixel density
screenWidthNumberScreen width in pixels
screenHeightNumberScreen height in pixels
windowWidthNumberAvailable window width in pixels
windowHeightNumberAvailable window height in pixels
statusBarHeightNumberStatus bar height in pixels
languageStringCurrent language code (e.g. "en", "cs")
versionStringApp version
systemStringAndroid version (e.g. "Android 12")
platformStringAlways "android"
fontSizeSettingNumberSystem font size setting in pixels
SDKVersionStringAndroid API level
darkModeBooleanWhether dark mode is enabled
tokenStringEncrypted authentication token for the current user and mini-app
albumAuthorizedBooleanPhoto library access permission status
cameraAuthorizedBooleanCamera permission status
locationAuthorizedBooleanLocation permission status
microphoneAuthorizedBooleanMicrophone permission status
bluetoothEnabledBooleanWhether Bluetooth is enabled
locationEnabledBooleanWhether GPS/location services are enabled
wifiEnabledBooleanWhether WiFi is connected
safeAreaObjectSafe area insets (for notches, etc.): left, right, top, bottom, width, height

Atlayo.system API

Native OS integrations for touch behavior, home-screen shortcuts, and the system share sheet. Available as window.Atlayo.system when your mini-app runs inside the Atlayo Android app.

Availability: Use Atlayo.system for the ergonomic JavaScript API. Underlying bridge methods are also exposed on AtlayoInterface. Android only.

setWebTouchFeedback

syncAndroid only
Atlayo.system.setWebTouchFeedback(enabled)

Disables default web-browser long-press text selection magnifiers and context menus, substituting native haptic feedback (HapticFeedbackConstants.LONG_PRESS) to give the web view a pure native app texture.

NameTypeDescriptionRequired
enabledBooleantrue disables selection/context menus and enables long-press haptic feedback; false restores default browser behaviorYes
Input
true
Output / Response
true  // bridge available
false // bridge unavailable
// Native-app touch feel (no magnifier / selection handles)
Atlayo.system.setWebTouchFeedback(true);

// Restore default browser long-press behavior
Atlayo.system.setWebTouchFeedback(false);

requestAppShortcut

asyncAndroid only
Atlayo.system.requestAppShortcut(id, label, icon, targetAction, callback)

Request pinning a dynamic launcher shortcut directly to the user's Android home screen (e.g. a "Scan & Pay" shortcut leading to a specific mini-app screen).

NameTypeDescriptionRequired
idStringUnique shortcut id within your mini-app (e.g. "scan_pay"). Defaults to the mini-app ID when emptyNo
labelStringShort label shown under the home-screen icon. Defaults to the mini-app name when emptyNo
iconStringBase64 PNG icon, optionally with data:image/png;base64, prefix. Defaults to the mini-app favicon when emptyNo
targetActionStringDeep-link action delivered via atlayo-shortcut-action event when opened from shortcutNo
callbackFunction | StringCallback function or name (default: onShortcutResult)No
Input
// Defaults: mini-app id, name, and favicon
Atlayo.system.requestAppShortcut('', '', '', '/scan-pay', 'onShortcutResult')

// Custom shortcut
Atlayo.system.requestAppShortcut(
  'scan_pay',
  'Scan & Pay',
  iconBase64Png,
  '/scan-pay',
  'onShortcutResult'
)
Output / Response
{
  "action": "requestAppShortcut",
  "success": true,
  "id": "scan_pay",
  "shortcutId": "my_app_scan_pay"
}
// Use mini-app defaults for id, label, and icon
Atlayo.system.requestAppShortcut('', '', '', '/scan-pay', function(result) {
    if (result.success) Atlayo.UI.toast('Shortcut requested');
});

Atlayo.system.requestAppShortcut(
    'scan_pay',
    'Scan & Pay',
    iconBase64Png,
    '/scan-pay',
    function(result) {
        if (result.success) Atlayo.UI.toast('Shortcut requested');
        else Atlayo.UI.alert(result.error || 'Could not create shortcut');
    }
);

document.addEventListener('atlayo-shortcut-action', function(e) {
    if (e.detail.targetAction === '/scan-pay') openScanAndPayScreen();
});
User confirmation: The main app shows a half-screen dialog first (Cancel / Agree) with only the mini-app name and shortcut label. The mini-app URL and targetAction are never shown to the user. The callback returns cancelled: true when declined.

shareSystemSheet

asyncAndroid only
Atlayo.system.shareSystemSheet(title, text, url, filesJson, callback)

Opens the native OS share sheet so mini-apps can share text, URLs, images, and files with external apps (WhatsApp, Signal, Email, etc.).

NameTypeDescriptionRequired
titleStringShare sheet title / email subjectNo
textStringPlain-text bodyNo
urlStringURL appended to shared textNo
filesJsonStringJSON array of { name, mimeType, data } with base64 file content. Default "[]"No
callbackFunction | StringCallback function or name (default: onShareResult)No
Input
const files = JSON.stringify([{
  name: 'receipt.jpg',
  mimeType: 'image/jpeg',
  data: receiptBase64
}]);

Atlayo.system.shareSystemSheet(
  'Your receipt',
  'Thanks for your order!',
  'https://shop.example.com/orders/123',
  files
)
Output / Response
{
  "action": "shareSystemSheet",
  "success": true
}
const files = JSON.stringify([{
    name: 'receipt.jpg',
    mimeType: 'image/jpeg',
    data: receiptBase64
}]);

Atlayo.system.shareSystemSheet(
    'Your receipt',
    'Thanks for your order!',
    'https://shop.example.com/orders/123',
    files,
    function(result) {
        if (!result.success) Atlayo.UI.alert(result.error || 'Share failed');
    }
);

showNativeScanner

asyncAndroid only
Atlayo.system.showNativeScanner(overlayConfigJson, callback)

Opens a native scanner UI backed by Google ML Kit. Supports two modes via mode in the config: barcode (CameraX + ML Kit barcode scanning — fast QR/barcode decode on background threads) and document (ML Kit Document Scanner — scan physical pages to digital JPEG/PDF with auto edge detection, cropping, and filters). Unlike openBarcodeScanner(), no camera frames are streamed into the WebView.

NameTypeDescriptionRequired
overlayConfigJsonObject | StringScanner mode and options (see below). Pass {} for barcode/QR defaultsNo
callbackFunction | StringCallback function or name (default: onNativeScanResult)No
FieldTypeDescriptionDefault
modeString"barcode" for QR/barcodes, "document" for scan-to-digital pages"barcode"
FieldTypeDescriptionDefault
promptStringHint text shown at the top of the scanner overlay"Point at a QR code"
hintStringAlias for prompt
showTorchBooleanShow the flashlight toggle buttontrue
vibrateBooleanShort vibration on successful scantrue
formatsString | ArrayBarcode formats: qr, ean13, code128, all, etc.["qr"]
FieldTypeDescriptionDefault
pageLimitNumberMaximum pages per scan session (0 = unlimited)0
galleryImportAllowedBooleanAllow importing existing photos from gallerytrue
scannerModeString"base", "base_with_filter", or "full" (ML cleanup + filters)"full"
resultFormatsArrayOutput types: ["jpeg"], ["pdf"], or ["jpeg","pdf"]["jpeg"]
includePdfBooleanShortcut to also request PDF when resultFormats is omittedfalse
searchablePdfBooleanBuild a searchable PDF with OCR text layer (alias: ocr). Uses ML Kit Text Recognition + custom PDF builder. Text can be selected/copied in PDF viewersfalse
ocrLanguageStringOCR script when searchablePdf is true: latin, chinese, japanese, korean, devanagarilatin
Input
// Barcode / QR
Atlayo.system.showNativeScanner({
  mode: 'barcode',
  prompt: 'Scan payment QR',
  formats: ['qr']
})

// Searchable document PDF (selectable text)
Atlayo.system.showNativeScanner({
  mode: 'document',
  searchablePdf: true,
  ocrLanguage: 'latin',
  scannerMode: 'full'
})
Output / Response
// Barcode mode
{
  "action": "showNativeScanner",
  "mode": "barcode",
  "success": true,
  "text": "https://pay.example.com/abc123",
  "format": "QR_CODE"
}

// Document mode
{
  "action": "showNativeScanner",
  "mode": "document",
  "success": true,
  "pageCount": 2,
  "pages": [
    { "index": 0, "mimeType": "image/jpeg", "data": "<base64>" }
  ],
  "pdf": {
    "mimeType": "application/pdf",
    "pageCount": 2,
    "searchable": true,
    "data": "<base64>"
  }
}
// QR / barcode
Atlayo.system.showNativeScanner({ mode: 'barcode', formats: ['qr'] }, function(result) {
    if (result.success) handleQrPayload(result.text);
});

// Searchable PDF — text can be selected/copied in PDF viewers
Atlayo.system.showNativeScanner({
    mode: 'document',
    searchablePdf: true,
    ocrLanguage: 'latin'
}, function(result) {
    if (result.success && result.pdf) {
        Atlayo.system.downloadFile('scan.pdf', 'application/pdf', result.pdf.data);
    }
});
Document mode uses Google Play services' ML Kit Document Scanner UI. Set searchablePdf: true to run ML Kit Text Recognition on each page and embed an OCR text layer (white invisible glyphs over the scan) so PDF viewers can select and search text. Requires Google Play services and ~1.7GB device RAM.

downloadFile

asyncAndroid only
Atlayo.system.downloadFile(name, mimeType, data, callback)

Saves a file to the device's public Downloads folder. Accepts base64-encoded file content (optionally with a data:…;base64, prefix). On Android 10+ uses MediaStore scoped storage; no storage permission is required on modern devices.

NameTypeDescriptionRequired
nameStringFilename including extension (e.g. "receipt.pdf")Yes
mimeTypeStringMIME type (e.g. application/pdf, image/jpeg)No
dataStringBase64 file bytesYes
callbackFunction | StringCallback function or name (default: onDownloadResult)No
Input
Atlayo.system.downloadFile(
  'scan-2026-04-12.pdf',
  'application/pdf',
  pdfBase64
)
Output / Response
{
  "action": "downloadFile",
  "success": true,
  "name": "scan-2026-04-12.pdf",
  "mimeType": "application/pdf",
  "size": 48231,
  "path": "Download/scan-2026-04-12.pdf",
  "uri": "content://..."
}
// Save scanned document PDF to Downloads
Atlayo.system.showNativeScanner({
    mode: 'document',
    resultFormats: ['pdf']
}, function(scan) {
    if (scan.success && scan.pdf) {
        Atlayo.system.downloadFile(
            'document.pdf',
            'application/pdf',
            scan.pdf.data,
            function(dl) {
                if (dl.success) Atlayo.UI.toast('Saved to Downloads');
            }
        );
    }
});

Atlayo.crypto API

Hardware-backed cryptographic operations via Android Keystore for secure wallets, P2P apps, and offline-first solutions. Keys are scoped per mini-app; private keys never leave secure hardware.

Security: Private keys are stored in Android Keystore / Secure Enclave and cannot be exported. Signing requires biometric authentication on supported devices.

generateSecureKeyPair

asyncAndroid only
Atlayo.crypto.generateSecureKeyPair(alias, algorithm, callback)

Generate an asymmetric key pair in hardware-backed secure storage. The private key never leaves the device's secure hardware.

NameTypeDescriptionRequired
aliasStringLogical key name within your mini-app (e.g. "wallet_signing_key"). Scoped per mini-app automaticallyYes
algorithmString"EC" (default, P-256) or "RSA" (2048-bit)No
callbackFunction | StringCallback function or name (default: onKeyPairResult)No
Input
Atlayo.crypto.generateSecureKeyPair('wallet_signing_key', 'EC')
Output / Response
{
  "action": "generateSecureKeyPair",
  "success": true,
  "alias": "atlayo_my_app_wallet_signing_key",
  "algorithm": "EC",
  "publicKey": "<base64 SPKI>",
  "publicKeyFormat": "SPKI",
  "alreadyExists": false
}
Atlayo.crypto.generateSecureKeyPair('wallet_signing_key', 'EC', function(result) {
    if (result.success) {
        console.log('Public key:', result.publicKey);
        registerPublicKeyWithBackend(result.publicKey);
    } else {
        Atlayo.UI.alert(result.error || 'Key generation failed');
    }
});

signPayloadNatively

asyncAndroid only
Atlayo.crypto.signPayloadNatively(alias, payloadJson, callback)

Sign a cryptographic message or transaction payload using a hardware-protected key. Biometric authentication (fingerprint or face unlock) is required before signing.

NameTypeDescriptionRequired
aliasStringKey alias previously created with generateSecureKeyPairYes
payloadJsonString | ObjectPayload to sign. Raw string, or object with payload, optional title / subtitle for biometric promptYes
callbackFunction | StringCallback function or name (default: onSignResult)No
Input
Atlayo.crypto.signPayloadNatively('wallet_signing_key', {
  payload: JSON.stringify({ to: '0xABC...', amount: '1.5', nonce: 42 }),
  title: 'Sign transaction',
  subtitle: 'Authorize transfer of 1.5 tokens'
})
Output / Response
{
  "action": "signPayloadNatively",
  "success": true,
  "signature": "<base64>",
  "algorithm": "SHA256withECDSA"
}
const txPayload = JSON.stringify({
    to: '0xABC...',
    amount: '1.5',
    nonce: 42
});

Atlayo.crypto.signPayloadNatively('wallet_signing_key', {
    payload: txPayload,
    title: 'Sign transaction',
    subtitle: 'Authorize transfer of 1.5 tokens'
}, function(result) {
    if (result.success) submitSignedTransaction(txPayload, result.signature);
    else Atlayo.UI.alert(result.error || 'Signing cancelled');
});

Device Features

Access device hardware: GPS, motion sensors, barcode scanner, biometrics, contacts, and audio.

Camera vs Barcode: Use openCamera() for photos/videos (see Camera API). Use scanBarcode() only for QR/barcode scanning.

getLocation

async
AtlayoInterface.getLocation(requestJson)

Get current GPS coordinates. Requires gps permission.

NameTypeDescriptionRequired
requestJsonString (JSON)Optional callback (default: onLocationResult)Yes
Input
{ "callback": "onLocationData" }
Output / Response
{
  "latitude": 50.0755, "longitude": 14.4378,
  "accuracy": 12.5, "altitude": 200,
  "timestamp": 1718640000000
}
AtlayoInterface.getLocation(JSON.stringify({ callback: "onLocationData" }));
window.onLocationData = function(result) {
    if (result.error) console.error(result.error);
    else console.log("Lat:", result.latitude, "Lng:", result.longitude);
};

startMotionSensor

async
AtlayoInterface.startMotionSensor(requestJson)

Start accelerometer and gyroscope streaming (~60 ms interval).

NameTypeDescriptionRequired
requestJsonString (JSON)Optional callback (default: onMotionSensorData)Yes
Input
{ "callback": "onMotionData" }
Output / Response
{
  "action": "motionSensorData", "success": true,
  "data": {
    "accelerometer": { "x": 0.1, "y": 9.8, "z": 0.2 },
    "gyroscope": { "x": 0.01, "y": 0.0, "z": 0.0 }
  }
}
AtlayoInterface.startMotionSensor(JSON.stringify({ callback: "onMotionData" }));
window.onMotionData = function(result) {
    if (result.success) console.log("Tilt X:", result.data.accelerometer.x);
};

stopMotionSensor

async
AtlayoInterface.stopMotionSensor(requestJson)

Stop motion sensor streaming.

Input
{}
Output / Response
void
AtlayoInterface.stopMotionSensor(JSON.stringify({}));

scanBarcode

async
AtlayoInterface.scanBarcode(requestJson)

Open camera to scan a barcode or QR code.

NameTypeDescriptionRequired
requestJsonString (JSON)Optional callback (default: onScanResult)Yes
  • AZTEC
  • CODABAR
  • CODE_39
  • CODE_93
  • CODE_128
  • DATA_MATRIX
  • EAN_8
  • EAN_13
  • ITF
  • MAXICODE
  • PDF_417
  • QR_CODE
  • RSS_14
  • UPC_A
  • UPC_E
  • UPC_EAN_EXTENSION

The detected format is returned in the format response field.

Input
{ "callback": "onBarcodeScanned" }
Output / Response
{
  "action": "scanBarcode", "success": true,
  "text": "https://example.com", "format": "QR_CODE"
}
AtlayoInterface.scanBarcode(JSON.stringify({ callback: "onBarcodeScanned" }));
window.onBarcodeScanned = function(result) {
    if (result.success) document.getElementById('scanResult').textContent = result.text;
};

authenticateBiometric

async
AtlayoInterface.authenticateBiometric(requestJson)

Initiate fingerprint or face recognition.

NameTypeDescriptionRequired
requestJsonString (JSON)Optional callback (default: onFingerprintResult)Yes
Input
{ "callback": "onBiometricAuth" }
Output / Response
{ "action": "authenticateBiometric", "success": true }
AtlayoInterface.authenticateBiometric(JSON.stringify({ callback: "onBiometricAuth" }));
window.onBiometricAuth = function(result) {
    if (result.success) unlockSecureContent();
    else Atlayo.UI.alert('Auth failed: ' + result.error);
};

selectContact

async
AtlayoInterface.selectContact(requestJson)

Open native contact picker (cloud-synced Atlayo contacts).

NameTypeDescriptionRequired
requestJsonString (JSON)Optional callback (default: onContactResult)Yes
Input
{}
Output / Response
{
  "action": "selectContact", "success": true,
  "contact": {
    "displayName": "Jane Doe",
    "phoneNumbers": [{ "value": "+420123456789", "type": "mobile" }]
  }
}
AtlayoInterface.selectContact(JSON.stringify({ callback: "onContactSelected" }));
window.onContactSelected = function(result) {
    if (result.success && result.contact) {
        console.log(result.contact.displayName, result.contact.phoneNumbers[0].value);
    }
};
Contacts are loaded from the cloud via the main app socket. Device-only contacts not synced to cloud will not appear.

getHardwareStatus

asyncAndroid only
AtlayoInterface.getHardwareStatus(hardwareType)

Check if a specific hardware feature is supported and enabled on the device.

NameTypeDescriptionRequired
hardwareTypeStringOne of: gps, bluetooth, nfcYes
Input
"bluetooth"
Output / Response
{
  "hardware": "bluetooth",
  "supported": true,
  "enabled": false
}
AtlayoInterface.getHardwareStatus("bluetooth");

window.onHardwareStatus = function(status) {
    if (status.hardware === "bluetooth" && status.supported && !status.enabled) {
        // Prompt user to enable Bluetooth
    }
};

enableHardware

syncAndroid only
AtlayoInterface.enableHardware(hardwareType)

Open the Android system settings page to let the user enable the specified hardware feature.

NameTypeDescriptionRequired
hardwareTypeStringOne of: gps, bluetooth, nfcYes
Input
"bluetooth"
Output / Response
void
AtlayoInterface.enableHardware("bluetooth");

NFC API

Read, write, and emulate NFC tags.

Hardware limits: Android cannot emulate Mifare Classic or clone hardware UIDs. HCE is for custom systems where you control both reader and mini-app.

NFC Workflow

  1. startNfcDiscovery → wait for tag
  2. Connect (connectNfcA / connectMifareClassic / connectIsoDep)
  3. Read/write/transceive
  4. Close connection → stopNfcDiscovery

startNfcDiscovery

asyncAndroid only
AtlayoInterface.startNfcDiscovery(requestJson)

Start listening for NFC tags.

Input
{ "callback": "onNfcDiscovered" }
Output / Response
{ "id": "04A1B2C3", "techs": ["android.nfc.tech.NfcA"] }

connectNfcA

asyncAndroid only
AtlayoInterface.connectNfcA(requestJson)

Connect to discovered NFC-A tag.

Input
{ "callback": "onNfcConnected" }
Output / Response
{ "success": true, "message": "Connected" }

transceiveNfcA

asyncAndroid only
AtlayoInterface.transceiveNfcA(requestJson)

Send APDU command to NFC-A tag.

Input
{ "data": "FFCA000000", "callback": "onNfcTransceiveResult" }
Output / Response
{ "response": "0400" }

closeNfcA

asyncAndroid only
AtlayoInterface.closeNfcA()

Close NFC-A connection.

Output / Response
void

connectMifareClassic

asyncAndroid only
AtlayoInterface.connectMifareClassic(requestJson)

Connect to MifareClassic tag.

Input
{ "callback": "onMifareConnected" }
Output / Response
{ "success": true }

authenticateSectorWithKeyA

asyncAndroid only
AtlayoInterface.authenticateSectorWithKeyA(requestJson)

Authenticate MifareClassic sector with Key A.

Input
{ "sector": 0, "key": "FFFFFFFFFFFF" }
Output / Response
{ "success": true }

readBlockMifareClassic

asyncAndroid only
AtlayoInterface.readBlockMifareClassic(requestJson)

Read 16-byte block (authenticate sector first).

Input
{ "block": 4 }
Output / Response
{ "data": "00112233445566778899AABBCCDDEEFF" }

writeBlockMifareClassic

asyncAndroid only
AtlayoInterface.writeBlockMifareClassic(requestJson)

Write 16-byte block (32 hex chars).

Input
{ "block": 4, "data": "00112233445566778899AABBCCDDEEFF" }
Output / Response
{ "success": true }

closeMifareClassic

asyncAndroid only
AtlayoInterface.closeMifareClassic()

Close MifareClassic connection.

Output / Response
void

connectIsoDep

asyncAndroid only
AtlayoInterface.connectIsoDep(requestJson)

Connect to IsoDep tag (smart cards, EMV, passports).

Input
{}
Output / Response
{ "success": true }

transceiveIsoDep

asyncAndroid only
AtlayoInterface.transceiveIsoDep(requestJson)

Send APDU to IsoDep tag.

Input
{ "data": "00A4040007A0000000031010" }
Output / Response
{ "response": "9000" }

closeIsoDep

asyncAndroid only
AtlayoInterface.closeIsoDep()

Close IsoDep connection.

Output / Response
void

readIsoDepAids

asyncAndroid only
AtlayoInterface.readIsoDepAids(requestJson)

Reads supported Application IDs (AIDs) from a connected IsoDep card by querying the PPSE directory.

NameTypeDescriptionRequired
requestJsonString (JSON)callbackNo
Input
{ "callback": "onIsoDepAidsResult" }
Output / Response
{ "success": true, "aids": ["A0000000031010", "A0000000041010"] }
Not all IsoDep cards support the PPSE directory. If missing, it returns an error.
AtlayoInterface.readIsoDepAids(JSON.stringify({ callback: "onMyAidsResult" }));
window.onMyAidsResult = function(result) {
    console.log(result.aids);
};

stopNfcDiscovery

asyncAndroid only
AtlayoInterface.stopNfcDiscovery()

Stop NFC tag discovery.

Output / Response
void

emulateNfcCard

asyncAndroid only
AtlayoInterface.emulateNfcCard(requestJson)

Host Card Emulation — phone acts as NFC card. Reader must SELECT AID F0010203040506.

Input
{ "data": "48656C6C6F", "callback": "onNfcEmulationResult" }
Output / Response
{ "action": "cardRead" }  // when reader taps phone

stopNfcEmulation

asyncAndroid only
AtlayoInterface.stopNfcEmulation()

Stop NFC card emulation.

Output / Response
void

Bluetooth/BLE API

Interact with nearby Bluetooth devices like smart home devices, IoT kiosks, and wearables. Android only.

Permissions: Requires system Bluetooth permissions and user authorization for the specific Mini-App. These are handled automatically by the API.

openBluetoothAdapter

asyncAndroid only
AtlayoInterface.openBluetoothAdapter(requestJson)

Initializes the Bluetooth adapter. If permissions are missing, prompts the user.

Input
{ "callback": "onBluetoothAdapterOpened" }
Output / Response
{ "success": true, "message": "Bluetooth adapter initialized" }

startBluetoothDevicesDiscovery

asyncAndroid only
AtlayoInterface.startBluetoothDevicesDiscovery(requestJson)

Starts scanning for nearby BLE devices. Calls the callback each time a device is found. Optionally, pass an array of `services` (UUIDs) to filter the scan.

Input
{ "services": ["180D", "180F"], "callback": "onBluetoothDeviceFound" }
Output / Response
{ "device": { "name": "SmartBulb", "deviceId": "00:11:22:33:44:55", "rssi": -65 } }

stopBluetoothDevicesDiscovery

asyncAndroid only
AtlayoInterface.stopBluetoothDevicesDiscovery(requestJson)

Stops the ongoing BLE device scan.

Input
{ "callback": "onBluetoothDiscoveryStopped" }
Output / Response
{ "success": true, "message": "Discovery stopped" }

createBLEConnection

asyncAndroid only
AtlayoInterface.createBLEConnection(requestJson)

Connects to a specific BLE device by its deviceId (MAC address).

Input
{ "deviceId": "00:11:22:33:44:55", "callback": "onBLEConnectionStateChange" }
Output / Response
{ "deviceId": "00:11:22:33:44:55", "connected": true, "status": 0 }

writeBLECharacteristicValue

asyncAndroid only
AtlayoInterface.writeBLECharacteristicValue(requestJson)

Writes data to a specific characteristic on a connected BLE device. The value must be encoded as a Base64 string.

Input
{ 
  "deviceId": "00:11:22:33:44:55", 
  "serviceId": "0000180d-0000-1000-8000-00805f9b34fb",
  "characteristicId": "00002a37-0000-1000-8000-00805f9b34fb",
  "value": "AQI=", // Base64 encoded payload
  "callback": "onWriteComplete"
}
Output / Response
{ "success": true, "message": "Write initiated" }

onBLECharacteristicValueChange

async eventAndroid only
window.onBLECharacteristicValueChange(result)

Global callback triggered when a characteristic's value changes (notifications/indications). Ensure you assign this function in your mini-app's global scope.

Output / Response
{ 
  "deviceId": "00:11:22:33:44:55", 
  "serviceId": "0000180d-0000-1000-8000-00805f9b34fb",
  "characteristicId": "00002a37-0000-1000-8000-00805f9b34fb",
  "value": "AQI=" // Base64 encoded payload
}

Camera API

Built-in photo and video capture overlay. Android only — not available on Desktop.

User controls: Tap = photo, hold ~0.5s = video. Preview shows Cancel / Send. Only Send delivers media to your callback.

openCamera

asyncAndroid only
AtlayoInterface.openCamera(callback)
AtlayoInterface.openCamera(options, callback)

Open full-screen camera overlay. Callback runs once when user sends or cancels. Use fullScreen: false to keep the themed status bar and lay the camera out below it.

NameTypeDescriptionRequired
callbackFunctionCalled with result object (legacy: pass as first argument only)Yes
optionsObjectOptional settings when using openCamera(options, callback)No
options.fullScreenBooleanWhen true (default), camera extends edge-to-edge under a transparent status bar. When false, status bar stays as before and content starts below it.No
Input
// Default: edge-to-edge under transparent status bar
AtlayoInterface.openCamera(function(result) { ... });

// Keep status bar / inset layout
AtlayoInterface.openCamera({ fullScreen: false }, function(result) { ... });
Output / Response
{
  "success": true,
  "type": "image",
  "mimeType": "image/jpeg",
  "file": ""
}
// Cancelled:
{ "success": false, "error": "Cancelled" }
if (typeof AtlayoInterface.openCamera === 'function') {
    AtlayoInterface.openCamera({ fullScreen: true }, function(result) {
        if (!result.success) return;
        const url = URL.createObjectURL(result.file);
        document.getElementById('preview').src = url;
    });
} else {
    Atlayo.UI.alert('Camera not available on this platform');
}

Display & Upload

// Preview captured media
const blob = result.file instanceof Blob ? result.file
    : new Blob([result.file], { type: result.mimeType });
const url = URL.createObjectURL(blob);
document.getElementById('myPhotoPreview').src = url;
// Remember: URL.revokeObjectURL(url) when done

// Upload to server
const formData = new FormData();
formData.append('media', result.file, result.file.name || 'capture');
fetch('https://your-server.example/upload', { method: 'POST', body: formData });

File Picker Fallback (Desktop & Gallery)

<input type="file" id="mediaPicker" accept="image/*,video/*" style="display:none" />
<button onclick="document.getElementById('mediaPicker').click()">Select Media</button>

document.getElementById('mediaPicker').addEventListener('change', function(e) {
    const file = e.target.files[0];
    if (!file) return;
    const url = URL.createObjectURL(file);
    // show in <img> or <video> same as camera result
});
Reserved IDs: Do not use cameraVideo, cameraPreviewVideo, or cameraPreviewImg — they conflict with the injected camera UI.

Payment API

Process payments via Stripe Connect. Requires a payment API key from the Developer Portal.

Prerequisites: Create a payment key (pk_...) in the Developer Portal, complete Stripe Connect onboarding, and ensure users have wallet balance.
Legal: All transfers go through Stripe's licensed infrastructure.

atlayo_pay

async
atlayo_pay(options)

Charge the user via wallet balance. Requires biometric authentication.

NameTypeDescriptionRequired
amountNumberAmount in EUR (> 0)Yes
api_keyStringPayment key from Developer Portal (pk_...)Yes
descriptionStringPayment descriptionNo
recipientStringRecipient nameNo
callbackFunction|StringDefault: onPaymentResultNo
Input
{
  "amount": 10.50,
  "api_key": "pk_YOUR_KEY",
  "description": "Purchase item XYZ",
  "recipient": "My Store"
}
Output / Response
{
  "success": true,
  "transactionId": 12345,
  "payment_intent_id": "pi_...",
  "timestamp": 1718640000000
}
atlayo_pay({
    amount: 10.50,
    api_key: 'pk_YOUR_KEY',
    description: 'Purchase item XYZ',
    callback: function(result) {
        if (result.success) {
            Atlayo.UI.alert('Payment successful!', { title: 'Success' });
        } else {
            Atlayo.UI.alert('Failed: ' + result.error, { title: 'Error' });
        }
    }
});
Returns true if the request was sent, false if the API is unavailable.

Push Notification API (Server)

REST API for your backend to send push notifications to mini-app users.

Endpoint:
POST https://atlayo.com/developer_portal/api/v1/push_notification.php
Security: Never embed your server key (atlayo_sk_...) in client code.
Authorization: Bearer atlayo_sk_...
# or
X-Atlayo-Server-Key: atlayo_sk_...

POST /push_notification.php

server
POST https://atlayo.com/developer_portal/api/v1/push_notification.php

Send a push notification to a specific user of your mini-app.

NameTypeDescriptionRequired
app_idStringMini-app ID from Developer PortalYes
user_tokenStringEncrypted token from getSystemInfo().tokenYes
notificationObjectPayload: title, body, optional query_params, sound, vibrate, data, iconYes
Input
{
  "app_id": "my-awesome-app",
  "user_token": "",
  "notification": {
    "title": "Item expiring soon",
    "body": "Milk expires in 2 days",
    "query_params": "fridge=abc123",
    "sound": true,
    "vibrate": true,
    "data": { "type": "expiry_soon" }
  }
}
Output / Response
{
  "success": true,
  "message": "Notification sent successfully via WebSocket and FCM",
  "methods": ["WebSocket", "FCM"],
  "delivered": true
}
// Register user token in mini-app
AtlayoInterface.requestPermissions(JSON.stringify(['notifications']));
window.onPermissionsGranted = function() {
    const token = JSON.parse(AtlayoInterface.getSystemInfo()).token;
    fetch('https://your-backend.example/api/register', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token })
    });
};

// cURL from your server
curl -X POST "https://atlayo.com/developer_portal/api/v1/push_notification.php" \
  -H "Content-Type: application/json" \
  -H "X-Atlayo-Server-Key: atlayo_sk_YOUR_KEY" \
  -d '{"app_id":"my-app","user_token":"TOKEN","notification":{"title":"Hi","body":"Hello"}}' 
HTTPMeaning
401Missing server key header
403Invalid key, user not found, or notifications not granted
404app_id not found
400Invalid JSON or missing required fields

UI Library (Atlayo.UI)

Native-style UI components available as window.Atlayo.UI. Global alert() is overridden to use Atlayo.UI.alert().

Dialog-style methods return a wrapper with .hide(callback) for manual dismissal. Atlayo.UI is injected into the WebView after the page loads. Listen for the atlayo-ui-ready event or assign window.__onAtlayoUIReady before calling overlay components.
MethodTypeDescription
Atlayo.UI.dialog(options)OverlayBase dialog with custom title, content, and buttons
Atlayo.UI.alert(message, options)OverlayAlert dialog with OK button
Atlayo.UI.confirm(message, options)OverlayConfirmation dialog with multiple buttons
Atlayo.UI.toast(message, options)OverlayTemporary success/info toast
Atlayo.UI.loading(message, options)OverlayLoading spinner; call .hide() to dismiss
Atlayo.UI.actionSheet(menus, actions, options)OverlayBottom sheet with menu and cancel action rows
Atlayo.UI.topTips(content, options)OverlayTop error/warning tip banner
Atlayo.UI.picker(items, options)OverlaySingle-, multi-, or cascading column picker
Atlayo.UI.datePicker(options)OverlayYear / month / day picker
Atlayo.UI.form.validate(selector, callback, options)DOMValidate a form on submit
Atlayo.UI.form.checkIfBlur(selector, options)DOMValidate inputs on blur
Atlayo.UI.form.showErrorTips(error)DOMShow field validation error as topTips
Atlayo.UI.form.hideErrorTips(ele)DOMHide validation error for an input

Atlayo.UI.dialog

sync
Atlayo.UI.dialog(options)

Base dialog component. alert and confirm are built on top of this.

NameTypeDescriptionRequired
options.titleStringDialog titleNo
options.contentStringDialog body textNo
options.classNameStringCustom CSS classNo
options.buttonsArrayButtons: label, type (primary | default | warn), onClickNo

Dialog wrapper with .hide(callback) to close manually.

const dlg = Atlayo.UI.dialog({
    title: 'Confirm action',
    content: 'Proceed with this operation?',
    buttons: [
        { label: 'Cancel', type: 'default' },
        { label: 'OK', type: 'primary', onClick: function() { console.log('ok'); } }
    ]
});

Atlayo.UI.alert

sync
Atlayo.UI.alert(message, options)

Show a native-style alert dialog.

NameTypeDescriptionRequired
messageStringMessage textYes
options.titleStringDialog titleNo
options.buttonsArrayButtons with label, type, optional onClickNo
Input
Atlayo.UI.alert("Saved!", { title: "Success", buttons: [{ label: "OK", type: "primary" }] })
Output / Response
void
alert("Hello!");  // uses Atlayo.UI.alert automatically

Atlayo.UI.alert("Do you want to continue?", {
    title: "Confirm",
    buttons: [
        { label: "Cancel", type: "default" },
        { label: "OK", type: "primary" }
    ]
});

Atlayo.UI.confirm

sync
Atlayo.UI.confirm(message, options)

Show a confirmation dialog with action buttons.

NameTypeDescriptionRequired
messageStringMessage textYes
options.buttonsArrayButtons with label, type, onClickYes
Input
Atlayo.UI.confirm("Delete this item?", { title: "Delete", buttons: [...] })
Output / Response
void
Atlayo.UI.confirm("Are you sure?", {
    title: "Delete Item",
    buttons: [
        { label: "Cancel", type: "default" },
        { label: "Delete", type: "warn", onClick: function() { deleteItem(); } }
    ]
});

Atlayo.UI.toast

sync
Atlayo.UI.toast(message, options)

Show a temporary toast at the top of the screen.

NameTypeDescriptionRequired
messageStringToast textYes
options.durationNumberDuration in ms (default: 3000)No
options.classNameStringCustom CSS classNo
options.callbackFunctionCalled when toast closesNo
Input
Atlayo.UI.toast("Settings saved", { duration: 2000 })
Output / Response
void
Atlayo.UI.toast("Connection successful", { duration: 3000 });
Atlayo.UI.toast("Saved!", { duration: 2000, callback: function() { console.log('closed'); } });

Atlayo.UI.loading

sync
Atlayo.UI.loading(message, options)

Show loading indicator. Returns a wrapper with .hide(callback).

NameTypeDescriptionRequired
messageStringLoading messageNo
options.classNameStringCustom CSS classNo
Input
const loading = Atlayo.UI.loading("Loading...");
Output / Response
loading.hide(callback) — call to dismiss
const hideLoading = Atlayo.UI.loading("Loading data...");
fetch('/api/data').then(r => r.json()).then(data => {
    hideLoading.hide();
    renderData(data);
});

Atlayo.UI.actionSheet

sync
Atlayo.UI.actionSheet(menus, actions, options)

Show a bottom action sheet. menus are the primary options; actions is typically a cancel row at the bottom.

NameTypeDescriptionRequired
menusArrayPrimary actions: label, optional onClickYes
actionsArraySecondary actions (e.g. Cancel): label, onClickYes
options.titleStringSheet titleNo
options.classNameStringCustom CSS classNo
options.onCloseFunctionCalled when sheet closesNo
Atlayo.UI.actionSheet([
    { label: "Take Photo", onClick: function() {
        AtlayoInterface.openCamera(function(r) {
            if (r.success) Atlayo.UI.toast('Captured!');
        });
    }},
    { label: "Choose from Gallery", onClick: openGallery }
], [
    { label: "Cancel", onClick: function() {} }
], { title: "Select Image Source" });

Atlayo.UI.topTips

sync
Atlayo.UI.topTips(content, options)

Show a temporary tip banner at the top of the screen (typically for validation errors).

NameTypeDescriptionRequired
contentStringTip message textYes
optionsNumber | ObjectDuration in ms, or config objectNo
options.durationNumberAuto-hide delay in ms (default: 3000)No
options.classNameStringCustom CSS classNo
options.callbackFunctionCalled when tip closesNo
Atlayo.UI.topTips('Please fill in all required fields', 3000);
const tip = Atlayo.UI.topTips('Invalid email', { duration: 3000, callback: function() {} });
tip.hide();  // dismiss manually

Atlayo.UI.picker

sync
Atlayo.UI.picker(items, options) — or picker(col1, col2, options) / picker(col1, col2, col3, options)

Multi-column picker for single, multi-column, or cascading selections. Each item: { label, value, disabled?, children? }.

NameTypeDescriptionRequired
itemsArrayPicker data (1–3 columns; use multiple args for multi-column)Yes
options.defaultValueArrayPre-selected valuesNo
options.titleStringPicker titleNo
options.depthNumberColumn count 1–3 (inferred from data if omitted)No
options.onChangeFunctionCalled when selection changesNo
options.onConfirmFunctionCalled with selected value array on confirmNo
options.idStringCache key for remembered selectionNo
// Single column
Atlayo.UI.picker([
    { label: 'Option A', value: 0 },
    { label: 'Option B', value: 1 }
], { defaultValue: [1], onConfirm: function(result) { console.log(result); } });

// Cascading (e.g. category → subcategory)
Atlayo.UI.picker([
    { label: 'Food', value: 0, children: [{ label: 'Pizza', value: 1 }] },
    { label: 'Drink', value: 1, children: [{ label: 'Water', value: 2 }] }
], { defaultValue: [0, 1], onConfirm: function(r) { console.log(r); } });

Atlayo.UI.datePicker

sync
Atlayo.UI.datePicker(options)

Date picker for year, month, and day selection.

NameTypeDescriptionRequired
options.startNumber | String | DateStart year or date (default: 2000)No
options.endNumber | String | DateEnd year or date (default: 2030)No
options.defaultValueArrayDefault [year, month, day], e.g. [1991, 6, 9]No
options.cronStringRestrict selectable days, e.g. "* * 0,6" for weekends onlyNo
options.onChangeFunctionCalled when date changesNo
options.onConfirmFunctionCalled with [year, month, day] on confirmNo
Atlayo.UI.datePicker({
    start: 1990,
    end: 2030,
    defaultValue: [1991, 6, 9],
    onConfirm: function(result) { console.log(result); }  // [1991, 6, 9]
});

Atlayo.UI.form

sync
Atlayo.UI.form.validate(selector, callback, options)

Form validation helpers. Inputs use required, pattern, emptyTips, and notMatchTips attributes.

MethodDescription
form.validate(selector, callback, options)Validate all fields in a form; callback receives error object or null
form.checkIfBlur(selector, options)Validate individual fields on blur
form.showErrorTips(error)Show validation error via topTips (error.ele, error.msg)
form.hideErrorTips(ele)Hide error tips for a specific input element
<form id="myForm">
  <input type="tel" required pattern="[0-9]{11}"
         emptyTips="Enter phone" notMatchTips="Invalid phone">
</form>

Atlayo.UI.form.validate('#myForm', function(error) {
    if (!error) {
        const loading = Atlayo.UI.loading('Submitting...');
        submitForm().finally(function() { loading.hide(); });
    }
}, { regexp: { IDNUM: /^\d{17}[\dXx]$/ } });

Callbacks Reference

Global callback functions for asynchronous API responses. Override with custom callback names in request JSON.

CallbackTriggered ByResponse Shape
window.onPermissionsGrantedrequestPermissions{ given_name, family_name, phone_number, ... }
window.onStorageResponseset/get/remove/clearStorage{ action, key, success/found/data/removed/cleared }
window.onStorageErrorStorage errors{ error: "message" }
window.onScanResultscanBarcode{ action, success, text, format, error }
window.onFingerprintResultauthenticateBiometric{ action, success, error }
window.onContactResultselectContact{ action, success, cancelled, contact, error }
window.onShortcutResultAtlayo.system.requestAppShortcut{ action, success, id, shortcutId, cancelled, error }
window.onShareResultAtlayo.system.shareSystemSheet{ action, success, error }
window.onNativeScanResultAtlayo.system.showNativeScanner{ action, mode, success, text, format, pageCount, pages, pdf, cancelled, error }
window.onDownloadResultAtlayo.system.downloadFile{ action, success, name, mimeType, size, path, uri, error }
window.onKeyPairResultAtlayo.crypto.generateSecureKeyPair{ action, success, alias, algorithm, publicKey, publicKeyFormat, alreadyExists, error }
window.onSignResultAtlayo.crypto.signPayloadNatively{ action, success, signature, algorithm, error }
window.onLocationResultgetLocation{ latitude, longitude, accuracy, error }
window.onMotionSensorDatastartMotionSensor{ action, success, data: { accelerometer, gyroscope } }
window.onPaymentResultatlayo_pay{ success, transactionId, payment_intent_id, timestamp, error }
window.onNfcDiscoveredstartNfcDiscovery{ id, techs, error }
// Prefer custom callbacks for cleaner code
AtlayoInterface.setStorage(JSON.stringify({
    key: "settings", data: { v: 1 }, callback: "onSettingsSaved"
}));
function onSettingsSaved(response) {
    if (response.success) Atlayo.UI.toast("Saved");
}

Complete Examples

Working patterns combining multiple APIs.

Multi-API Mini-App Starter

<!DOCTYPE html>
<html><head><title>My Mini-App</title></head>
<body>
  <h1>My Mini-App</h1>
  <button onclick="requestUserData()">Get User Data</button>
  <button onclick="scanQR()">Scan QR</button>
  <button onclick="saveData()">Save Data</button>
  <div id="userName"></div>
  <div id="scanResult"></div>

  <script>
    window.addEventListener('load', function() {
        if (typeof AtlayoInterface === 'undefined') return;
        const info = JSON.parse(AtlayoInterface.getSystemInfo());
        if (info.darkMode) document.body.classList.add('dark-mode');
    });

    function requestUserData() {
        AtlayoInterface.requestPermissions(JSON.stringify(["given_name", "family_name"]));
    }
    window.onPermissionsGranted = function(data) {
        document.getElementById('userName').textContent = data.given_name + ' ' + data.family_name;
        Atlayo.UI.alert("Welcome " + data.given_name + "!");
    };

    function scanQR() { AtlayoInterface.scanBarcode(JSON.stringify({})); }
    window.onScanResult = function(r) {
        if (r.success) document.getElementById('scanResult').textContent = r.text;
    };

    function saveData() {
        AtlayoInterface.setStorage(JSON.stringify({
            key: "my_data", data: { ts: Date.now() }, callback: "onSaved"
        }));
    }
    function onSaved(r) { Atlayo.UI.toast(r.success ? "Saved!" : "Failed"); }
  </script>
</body></html>

Payment with Loading

function makePayment() {
    const hide = Atlayo.UI.loading('Processing payment...');
    atlayo_pay({
        amount: 10.00, api_key: 'pk_YOUR_KEY', description: 'Product',
        callback: function(result) {
            hide();
            if (result.success) enableProductAccess();
            else Atlayo.UI.alert('Failed: ' + result.error);
        }
    });
}

Best Practices

Guidelines for reliable mini-app development.

  • Check availability — verify AtlayoInterface exists before calling methods
  • Handle errors — implement error callbacks for all async operations
  • Request permissions early — ask on app load, not on first use
  • Use custom callbacks — cleaner than relying on global handlers
  • Parse JSON carefully — storage returns stringified data
  • Respect privacy — only request permissions you need
  • Test on real devices — biometrics, NFC, and camera need physical hardware
  • Platform fallbacks — use file picker when openCamera is unavailable

Getting Started (Desktop)

Mini-apps run in a separate window with AtlayoInterface injected automatically.

if (typeof AtlayoInterface !== 'undefined') {
    const sysInfo = JSON.parse(AtlayoInterface.getSystemInfo());
    console.log('Platform:', sysInfo.platform); // "desktop"
}

Storage API (Desktop)

Same API as Android. Data stored in localStorage with miniapp_storage_ prefix.

setStorage

asyncdesktop
AtlayoInterface.setStorage(storageJson)

Store a value.

NameTypeDescriptionRequired
storageJsonString (JSON)key, data, optional callbackYes
Input
{ "key": "pref", "data": { "theme": "dark" } }
Output / Response
{ "action": "setStorage", "key": "pref", "success": true }
AtlayoInterface.setStorage(JSON.stringify({ key: "pref", data: { theme: "dark" } }));

getStorage

asyncdesktop
AtlayoInterface.getStorage(requestJson)

Retrieve a value.

Input
{ "key": "pref" }
Output / Response
{ "action": "getStorage", "found": true, "data": "..." }
AtlayoInterface.getStorage(JSON.stringify({ key: "pref" }));

removeStorage

asyncdesktop
AtlayoInterface.removeStorage(requestJson)

Remove a key.

Input
{ "key": "pref" }
Output / Response
{ "action": "removeStorage", "removed": true }

clearStorage

asyncdesktop
AtlayoInterface.clearStorage(requestJson)

Clear all storage.

Input
{}
Output / Response
{ "action": "clearStorage", "cleared": true }
AtlayoInterface.clearStorage(JSON.stringify({}));

Permissions API (Desktop)

Same flow as Android. Additional keys: token. Phone numbers include + prefix.

requestPermissions

asyncdesktop
AtlayoInterface.requestPermissions(permissionsJson)

Request user data permissions.

NameTypeDescriptionRequired
permissionsJsonString (JSON array)given_name, family_name, phone_number, notifications, gps, token, bluetoothYes
Input
["given_name", "family_name", "phone_number"]
Output / Response
{ "given_name": "John", "family_name": "Doe", "phone_number": "+1234567890" }
AtlayoInterface.requestPermissions(JSON.stringify(["given_name", "family_name"]));
window.onPermissionsGranted = function(data) {
    console.log(data.given_name, data.family_name);
};

UI & System API (Desktop)

Status bar / navigation bar methods are no-ops on Desktop. getSystemInfo() returns desktop-specific data.

No-op on Desktop: setStatusBarColor, setTopBarBackgroundColor, setTopBarForegroundColor, setNavigationBarColor

getSystemInfo

syncdesktop
AtlayoInterface.getSystemInfo()

Returns desktop environment info.

Input
AtlayoInterface.getSystemInfo()
Output / Response
{
  "brand": "Desktop", "model": "Win32", "platform": "desktop",
  "darkMode": false, "token": "", "language": "en",
  "hardwareConcurrency": 8, "timezone": "Europe/Prague"
}
const info = JSON.parse(AtlayoInterface.getSystemInfo());
if (info.darkMode) document.body.classList.add('dark');
console.log('CPU cores:', info.hardwareConcurrency);
console.log('Screen:', info.screenPhysicalWidth, 'x', info.screenPhysicalHeight);
PropertyTypeDescription
brandString"Desktop"
modelStringNavigator platform (e.g. "Win32", "MacIntel")
platformString"desktop"
darkModeBooleanWhether dark mode is preferred (prefers-color-scheme: dark)
tokenStringEncrypted auth token (if logged in)
languageStringPrimary language code (e.g. "en", "cs")
languagesArrayPreferred languages in order
screenWidthNumberViewport width in pixels
screenHeightNumberViewport height in pixels
windowWidthNumberWindow inner width in pixels
windowHeightNumberWindow inner height in pixels
outerWidthNumberWindow outer width including window frame
outerHeightNumberWindow outer height including window frame
safeAreaObjectSafe area insets: { top, bottom, left, right } (all 0 on desktop)
pixelRatioNumberDevice pixel ratio (e.g. 2 for Retina)
screenAvailWidthNumberAvailable screen width (excluding taskbar)
screenAvailHeightNumberAvailable screen height (excluding taskbar)
screenPhysicalWidthNumberPhysical screen width in pixels
screenPhysicalHeightNumberPhysical screen height in pixels
colorDepthNumberDisplay color depth in bits
pixelDepthNumberDisplay pixel depth in bits
hardwareConcurrencyNumberNumber of logical CPU cores
deviceMemoryNumberApproximate RAM in GB (when available)
maxTouchPointsNumberMaximum touch points supported
navigatorPlatformStringPlatform identifier from navigator
onLineBooleanWhether the app is online
timezoneStringIANA timezone (e.g. "Europe/Prague")
timezoneOffsetNumberUTC offset in minutes
memoryLimitNumberJS heap size limit in bytes (when available)
memoryUsedNumberJS heap used in bytes (when available)
memoryTotalNumberJS heap total in bytes (when available)
orientationAngleNumberScreen orientation angle
orientationTypeStringScreen orientation type
connectionEffectiveTypeStringNetwork connection type (e.g. "4g", "wifi")
connectionDownlinkNumberNetwork downlink in Mbps
connectionRttNumberNetwork round-trip time in ms
connectionSaveDataBooleanWhether data saver mode is enabled

Device Features (Desktop)

Limited hardware access. Some methods return mock/stub responses.

requestNotification

asyncdesktop
AtlayoInterface.requestNotification(notificationJson)

Request main app to show a system notification via POST to /__api/request_notification.

NameTypeDescriptionRequired
notificationJsonString (JSON)title, body, icon, etc.Yes
Input
{ "title": "Hello", "body": "World" }
Output / Response
void

scanBarcode

asyncdesktop
AtlayoInterface.scanBarcode(requestJson)

Not supported — immediately returns error.

Input
{}
Output / Response
{ "action": "scanBarcode", "success": false, "error": "Camera not supported on desktop" }

authenticateBiometric

asyncdesktop
AtlayoInterface.authenticateBiometric(requestJson)

Mock success — no user interaction.

Input
{}
Output / Response
{ "action": "authenticateBiometric", "success": true }

selectContact

asyncdesktop
AtlayoInterface.selectContact(requestJson)

Native-style contact picker. Same response format as Android.

Input
{}
Output / Response
{ "action": "selectContact", "success": true, "contact": { "displayName": "..." } }
Camera: openCamera() is not available on Desktop. Use an HTML file input — see Camera API → File Picker Fallback.

Payment API (Desktop)

Payments are not processed on Desktop.

requestPayment

asyncdesktop
AtlayoInterface.requestPayment(requestJson)

Shows alert: "Payments verified on mobile app". No payment processed.

NameTypeDescriptionRequired
requestJsonString (JSON)Ignored on DesktopYes
Input
{}
Output / Response
Alert dialog shown
Use the mobile app or web checkout for production payments.

UI Library (Desktop)

Same Atlayo.UI components as Android. See the Atlayo.UI section for full documentation.

Available on Desktop: dialog, alert, confirm, toast, loading, actionSheet, topTips, picker, datePicker, form. Global alert() is overridden.
alert("Hello from mini-app!");
Atlayo.UI.toast("Saved!", { duration: 2000 });
Atlayo.UI.datePicker({ start: 2020, end: 2030, onConfirm: function(d) { console.log(d); } });

Callbacks (Desktop)

Same callback names as Android. Desktop-specific behavior noted.

CallbackDesktop Behavior
onStorageResponseSame as Android (localStorage backend)
onPermissionsGrantedSame as Android
onScanResultAlways success: false, error about camera
onFingerprintResultAlways success: true (mock)
onContactResultSame format as Android
Override default callbacks via callback key in request JSON.

AtlayoNET Overview

Custom internet infrastructure via domains.atlayo.com.

domains.atlayo.com is a portal in the Atlayo Browser for registering and managing virtual hosts on the Atlayo custom internet.

  • Domain Search — check availability of .atlayo domains
  • Domain Management — configure routing via the atlayo-tunnel agent
  • Pricing — currently $0; future 1-year rent model planned

Atlayo ID API

Federated login for public websites — "Login with Atlayo ID". Users authenticate and grant scoped data access inside the Atlayo Android app.

Base URL: https://atlayo.com/developer_portal/api/identity/
JavaScript SDK: https://atlayo.com/developer_portal/js/atlayo-id.js
Real-time updates: WebSocket at wss://atlayo.com:8443 (event join_identity_room)

Overview

Atlayo ID works like OAuth 2.0 for the Atlayo ecosystem. A website starts an auth session, the user approves it on their phone (QR scan or phone-number push), and the website receives scoped user data plus an access token.

  1. Authorize — website creates a session and shows QR code or phone form
  2. Approve — user reviews requested scopes in the Atlayo app and taps Allow
  3. Token — website exchanges the approved session for an access token
  4. Userinfo — optional: fetch user profile with Bearer token

Supported Scopes

Websites can request profile fields only. A per-site encrypted token is always returned automatically after login — it is not a scope.

ScopeDescription
given_nameUser first name
family_nameUser last name
phone_numberPhone number (E.164 digits)
genderUser gender (as stored in the Atlayo profile)
languageApp language — the language the user has set in the Atlayo app (e.g. en, cs)
birthdateDate of birth (YYYY-MM-DD)
emailEmail address

User Token (auto-provided)

After approval, every login response includes a token field — an encrypted identifier unique to the user and your website domain. Use it on your backend to recognize returning users.

{
  "given_name": "John",
  "family_name": "Doe",
  "phone_number": "420601123456",
  "token": "xK9mP2...base64..."
}

Your backend resolves users with the site domain (or registered client domain) as the encryption key. The same user gets a different token on each website.

POST /authorize.php

REST

Start a new login session. Returns a QR payload and session token.

{
  "client_id": "your_client_id",
  "scopes": ["given_name", "family_name", "phone_number"],
  "origin": "example.com",
  "redirect_uri": "https://example.com/callback",
  "state": "optional-csrf-token",
  "login_method": "qr",
  "clientGeo": { "country": "CZ", "city": "Prague" }
}
Response
{
  "success": true,
  "sessionToken": "abc123...",
  "expiresAt": "2026-07-02 12:05:00",
  "clientName": "My Website",
  "requestedScopes": ["given_name", "family_name"],
  "scopeLabels": ["First name", "Last name"],
  "qrPayload": "{\"v\":1,\"t\":\"...\",\"sc\":[...]}",
  "qrDeepLink": "atlayo://identity/..."
}

POST /phone.php

REST

Attach a phone number to an existing session. Sends a login request to the user's Atlayo app.

{
  "session_token": "abc123...",
  "phone_number": "+420601123456"
}

GET /status.php?token=...

REST

Poll session status from the website. Returns loggedIn: true when the user approved on their phone.

POST /token.php

REST

Exchange an approved session for an access token. Public clients (browser SDK) send client_id + session_token only. Confidential clients also send client_secret.

{
  "client_id": "your_client_id",
  "session_token": "abc123..."
}
Response
{
  "success": true,
  "access_token": "....",
  "token_type": "Bearer",
  "expires_in": 300,
  "user": {
    "given_name": "John",
    "family_name": "Doe",
    "phone_number": "420601123456",
    "token": "encrypted-site-specific-token"
  },
  "scopes": ["given_name", "family_name"]
}

GET /userinfo.php

REST

Fetch user data with Authorization: Bearer <access_token>.

JavaScript SDK

browser
AtlayoID — client SDK

Include the SDK on any website to add "Login with Atlayo ID" with QR and phone flows.

<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.min.js"></script>
<script src="https://atlayo.com/developer_portal/js/atlayo-id.js"></script>

<div id="atlayo-qr"></div>
<input id="phone" type="tel" placeholder="+420 601 123 456">
<button id="phone-login">Login with phone</button>

<script>
const client = new AtlayoID({
  clientId: 'your_client_id',
  scopes: ['given_name', 'family_name', 'phone_number'],
  onSuccess: (result) => {
    console.log('User:', result.user);
    console.log('Access token:', result.accessToken);
  },
  onError: (err) => alert(err.message)
});

// QR login
client.loginWithQR(document.getElementById('atlayo-qr'));

// Phone login
document.getElementById('phone-login').onclick = async () => {
  await client.authorize({ loginMethod: 'phone' });
  await client.loginWithPhone(document.getElementById('phone').value);
};
</script>

QR Payload Format

The QR code contains compact JSON scanned by the Atlayo app:

{
  "v": 1,
  "s": 1,
  "t": "session_token_hex",
  "e": 1782070865,
  "n": "Website Name",
  "c": "client_id",
  "sc": ["given_name", "family_name"],
  "a": { "c": "CZ", "ci": "Prague", "q": "1.2.3.4" }
}

Deep link equivalent: atlayo://identity/<base64-json>

NFC Identity & Verification API

Cryptographically secure identity verification for businesses and developers.

The Atlayo app uses Ed25519 asymmetric cryptography to secure NFC business cards and the "Share Mine" (HCE) feature. This prevents tampering and identity theft (replay attacks).

How it Works

When an Atlayo user shares their identity via NFC, the payload is cryptographically signed by the Atlayo backend.

  • Tamper-Proof: The signature guarantees that the name and phone number have not been modified.
  • Anti-Replay (Share Mine): When using the "Share Mine" feature, the payload includes an exp timestamp valid for 24 hours. If an attacker copies the NFC data, it becomes useless the next day.
Example NFC Payload (JSON)
{
  "type": "atlayo_profile",
  "given_name": "John",
  "family_name": "Doe",
  "phone_number": "1234567890",
  "exp": 1782070865,
  "sig": "PnZwtyYi...[base64]...TODQ=="
}

Verify Identity API

REST API

Businesses can verify an Atlayo NFC payload remotely using this public API endpoint.

POST https://atlayo.com/api/nfc_identity.php
{
  "action": "verify",
  "payload": { /* The exact JSON object scanned from the NFC tag */ }
}
Success Response (200 OK)
{
  "status": 200,
  "verified": true,
  "data": {
    "type": "atlayo_profile",
    "given_name": "John",
    "family_name": "Doe",
    "phone_number": "1234567890",
    "exp": 1782070865
  }
}
Error Response (400 Bad Request)
{
  "status": 400,
  "verified": false,
  "error": "Invalid signature" // or "Token expired"
}

Testing Tool: You can manually test and verify payloads using the NFC Identity Verifier in the Developer Portal.