Building a Kiosk App
Build a dedicated scanning and check-in/check-out application using the Stockaj Kiosk API.
Overview
A kiosk app is a dedicated station — typically a tablet or desktop at a warehouse entrance — where users scan QR codes to quickly identify items, check rental status, and perform actions.
Prerequisites
- Stockaj account with Starter plan or above (API access required)
- API token with
kiosk:scanability - Device with camera (for QR scanning) or barcode reader
Architecture
┌──────────────────────────────┐
│ Kiosk Device │
│ ┌────────────────────────┐ │
│ │ Camera / Scanner │ │
│ │ (reads QR code) │ │
│ └──────────┬─────────────┘ │
│ │ │
│ ┌──────────▼─────────────┐ │
│ │ Kiosk App │ │
│ │ (web or native) │ │
│ └──────────┬─────────────┘ │
└─────────────┼────────────────┘
│ HTTPS
▼
┌──────────────────────────────┐
│ Stockaj API │
│ POST /api/v2/kiosk/scan │
│ GET /api/v2/kiosk/search │
│ PATCH /api/v2/rentals/{id} │
└──────────────────────────────┘
Step 1: Set Up Authentication
Create a dedicated API token for your kiosk:
- Go to Settings → API Tokens.
- Create a token named
kiosk-warehouse-main(or similar). - Select abilities:
kiosk:scan— Required for scan and searchrents:read— View rental detailsrents:update— Update rental status (for check-in/check-out)items:read— View item details
Step 2: Implement QR Scanning
Use a browser-based QR scanner library or a native camera API:
// Using html5-qrcode library
import { Html5QrcodeScanner } from 'html5-qrcode';
const scanner = new Html5QrcodeScanner('reader', {
qrbox: { width: 300, height: 300 },
fps: 10,
});
scanner.render(async (decodedText) => {
// Send scanned code to Stockaj
const result = await scanCode(decodedText);
displayResult(result);
});
Step 3: Call the Scan API
const API_BASE = 'https://app.stockaj.com/api/v2';
const TOKEN = process.env.STOCKAJ_KIOSK_TOKEN;
async function scanCode(code) {
const response = await fetch(`${API_BASE}/kiosk/scan`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${TOKEN}`,
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ code }),
});
return response.json();
}
Step 4: Display Results
function displayResult(result) {
if (!result.found) {
showError(`Item not found: ${result.message}`);
return;
}
// Show item info
showItemCard({
name: result.item.name,
code: result.item.code,
category: result.item.category,
available: result.item.available_quantity,
});
// Show variant info (if variant was scanned)
if (result.variant) {
showVariantCard({
serial: result.variant.serial_number,
condition: result.variant.condition,
available: result.variant.is_available,
});
}
// Show rental info (if item is currently rented)
if (result.rental) {
showRentalCard({
status: result.rental.status,
renter: result.renter.name,
returnDate: result.rental.expected_return_date,
});
}
}
Step 5: Implement Search
Add a search bar for manual item lookup:
async function searchItems(query) {
const response = await fetch(
`${API_BASE}/kiosk/search?q=${encodeURIComponent(query)}&limit=10`,
{
headers: {
'Authorization': `Bearer ${TOKEN}`,
'Accept': 'application/json',
},
}
);
const { results } = await response.json();
displaySearchResults(results);
}
Step 6: Add Check-In/Check-Out
Use the Rentals API to update rental status:
async function updateRentalStatus(rentalId, newStatus) {
const response = await fetch(`${API_BASE}/rentals/${rentalId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${TOKEN}`,
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ status: newStatus }),
});
return response.json();
}
// Usage
await updateRentalStatus(42, 'finished'); // Check-in (return)
await updateRentalStatus(43, 'dispatched'); // Check-out
UI Recommendations
For kiosk applications:
- Large touch targets — Buttons should be at least 48px for touch screens
- High contrast — Use clear colors and large fonts
- Auto-reset — Clear the screen after a period of inactivity
- Sound feedback — Play audio cues for successful/failed scans
- Continuous scanning — Auto-restart the scanner after each result
- Offline queue — Queue actions when network is unavailable
Security Considerations
- Use a dedicated API token with minimal abilities
- Lock down the kiosk device — Use kiosk mode or guided access
- HTTPS only — Ensure all API calls use HTTPS
- Store the token in environment variables, never in client-side code
- Consider a backend proxy to keep the token server-side