Skip to main content

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:scan ability
  • 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:

  1. Go to Settings → API Tokens.
  2. Create a token named kiosk-warehouse-main (or similar).
  3. Select abilities:
    • kiosk:scan — Required for scan and search
    • rents:read — View rental details
    • rents: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,
});
}
}

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