Stocky · version 5.8

Inventory, point of sale, online store & accounting

One Laravel application for the counter, the stockroom, the web shop and the books. A touch-first register that keeps selling offline, live stock across every warehouse, purchases and returns, double-entry accounting, HRM, sixty reports and a storefront with five themes. This guide covers installing it and running it.

In a hurry? Upload the files, open your domain, and follow the four-step installer. Then read Your first hour — the shortest path from an empty install to a shop that can scan a product, take cash and print a receipt.

Welcome

Stocky is one system for one business. The product the cashier scans is the same row the online shop sells, the row a WooCommerce or Shopify sync pushes, the row a purchase order restocks and the row the stock-aging report counts. Nothing is copied between screens, so nothing has to be reconciled — one catalogue, one stock figure, every channel.

/next/dashboard
The Stocky dashboard
The dashboard: today's sales, purchases, returns and dues per warehouse, with the charts and lists below.

What is in the box

Point of sale

Touch-first register with barcode and camera scanning, hold and drafts, split payments, promotions, registers, receipts, a customer display and an offline queue.

Products & stock

Single, variable, service and combo products; multi-warehouse stock with rack locations; batches and expiry; serial numbers; adjustments, transfers, counts and damages.

Buying & selling

Sales, quotations, purchases, sale and purchase returns, shipments, a customer ledger and supplier history; PDF, email, SMS and print on every document.

Online store

Five themes on one catalogue, twelve payment gateways, shipping zones, coupons, flash sales, reviews, wishlists, returns and a customer account.

Customer portal

A separate login for business customers: invoices, payments, statement, quotations, appointments, contracts and a knowledge base.

Money

Cash accounts, deposits and expenses, plus double-entry accounting that posts itself: chart of accounts, journals, trial balance, P&L, balance sheet and tax summary.

HRM

Companies, departments, shifts, employees, attendance, leave and payroll; recruitment and meetings as separate modules.

Business modules

Projects, bookings, service jobs, subscriptions, manufacturing, assets, fleet, kitchen display, documents, contracts, marketing, hospital and school — each on a switch.

Integrations

WooCommerce, Shopify, Salla, Jumia, PrestaShop, QuickBooks, Xero, Google Sheets, Mailchimp, Slack, Telegram, Google Calendar, ZATCA and Stripe.

Reports

Sixty report screens with a date range, a warehouse filter and Excel or PDF export, plus analytics, a 3D sales dashboard and question-driven AI reports.

Platform

Roles with 300+ permissions, users scoped to warehouses, 24 languages with RTL, light and dark themes, installable PWAs, a browser installer and an in-panel updater.

Mobile

A Bearer-token API for the separately sold companion app, with branding and module switches in Settings → Mobile App.

How to read this guide

Sections follow the order you will actually need them: install it, set the business up, then each module in the order the sidebar lists it. Every screen named here exists in the product — where something is deliberately absent it is listed under Deliberately not here rather than described as if it were built. Paths such as Settings → POS Settings refer to the sidebar; the address bar shows the same page under /next/….

The shape of every screen

Lists work the same way throughout: a search box and filters at the top of the card, a table, paging at the bottom, and export buttons where a list is worth exporting. Record pages open with a header — the reference, the status pills, the buttons that change its state — and then the detail. The POS is the exception: it is a full-screen application of its own, opened from the purple POS button in the header.

Server requirements

Stocky runs on ordinary PHP hosting. There is no Docker, no Node on the server and nothing to compile — the front-end assets ship already built. Cron and a queue worker are optional; see Cron & queue for what they add.

WhatNeedsNotes
PHP8.2 or newer8.2, 8.3 and 8.4 all work. The installer shows the version it found.
DatabaseMySQL 8.0+ or MariaDB 10.6+Create an empty database first; the installer fills it.
Extensionsopenssl, pdo, pdo_mysql, mbstring, curl, tokenizer, xml, ctype, fileinfo, gd, json, bcmath, zipAll standard. The installer checks each one and names the missing ones.
Web serverApache with mod_rewrite, or NginxPoint the domain at public/. The shipped .htaccess handles the rewrites.
Writable.env, storage/, bootstrap/cache/, public/images/Usually 755 on folders, 644 on files. Product images and uploads land in public/images.
HTTPSRequired for the camera scanner and PWA installBrowsers only expose the camera and the install prompt on secure origins. Everything else works over plain HTTP.
Memory256 MB PHP memory_limit recommendedLarge imports and PDF exports are the hungry operations.

Point the domain at public/, not at the folder above it. If the document root is the project folder, anyone can download your .env — which holds the database password and the application key. On cPanel this is Domains → Document Root. If your host truly will not allow it, the shipped .htaccess and server.php in the project root rewrite requests into public/; still prefer the proper document root.

Optional hardware

Nothing is bundled and nothing is proprietary. A USB or Bluetooth barcode scanner behaves as a keyboard and needs no driver. A phone or tablet camera scans in the browser. Thermal receipt printers print through the browser dialog, silently through QZ Tray on the cashier's computer, or directly to a network printer by IP address. Cash drawers kick through the receipt printer. Label printers take the barcode sheets. Digital scales that print weight-embedded barcodes are read as product plus kilograms.

Installing Online

Stocky installs itself in a browser. You do not need shell access, phpMyAdmin or a command line.

  1. Upload and unzip

    Put the contents of the ZIP on your server and point the domain at the public/ folder. Everything is included — you do not need to run composer install or npm.

  2. Open /setup

    Browse to https://your-domain/setup. You land on the requirements check. Every card must be green — the PHP version, the twelve extensions and the ZipArchive class. If one is not, enable it on the server and press Re-check requirements. Nothing has been written yet.

    /setup
    Installer step 1: server requirements
    Step 1 of 4. Each requirement is checked on your server and named if it is missing.
  3. Application settings

    The application name, the environment (Production for a live shop), debug mode (Off on a live server), an application key — press Generate — and the application URL, exactly as people will type it, with https://. All of this lands in .env and can be edited there later.

    /setup/step-1
    Installer step 2: application settings
    Step 2 of 4. Name, environment, debug mode, key and URL.
  4. Database

    Host, port, database name, username and password for an empty MySQL database. Press Test connection; the Continue button only appears once the test passes.

    /setup/step-2
    Installer step 3: database connection
    Step 3 of 4. Test the connection before you continue.
  5. Review and install

    Check the summary, then press Install Stocky. This writes .env, creates every table, installs the API keys and seeds the reference data: the Owner role, the permissions, the default warehouse, currencies, payment methods, settings and the translations for all 24 languages. Keep the tab open; it can take a few minutes on slow hosting.

  6. Sign in

    The finish page shows the default administrator: admin@example.com with the password 123456. Press Go to login.

Change the administrator password right after your first login. It is printed in this guide and on the installer's finish page. Open the user menu (top right) → Profile, or edit the account under User Management → Users — change the email as well.

The installer seals itself. Once it finishes, every /setup address answers 403. The seal is a file: storage/app/public/installed. Delete it to open the wizard again on a broken install — and if /setup is ever reachable when it should not be, that file is the first thing to check.

If the install fails

Message mentionsWhat to do
Access denied for userWrong database username or password. Go back a step and re-test.
Unknown databaseThe database does not exist. Create an empty one in your hosting panel and use that name.
Permission denied / failed to open stream.env, storage/ or bootstrap/cache/ is not writable. Set folders to 755 and files to 644, owned by the web server user.
Maximum execution timeRaise max_execution_time to 300 for the install, then run the installer again.
Base table already existsA previous attempt got half-way. Drop the tables (or the database) and run the installer again.
A blank page or 500 after Install StockyTurn debug mode on in .env (APP_DEBUG=true) to see the reason, or read storage/logs/laravel.log. Turn it off again afterwards.

Installing Locally

To try Stocky on a Windows computer before you go live, install it on Laragon or XAMPP. The browser installer is the same one described above; only the preparation differs. Laragon is the easier of the two — it creates a local domain pointing at public/ on its own, and it ships MySQL 8. XAMPP needs a virtual host written by hand.

A local install is for trying things out, training staff and testing changes. An online store, payment gateways, marketplace webhooks and customer emails need a real server with a public https:// address.

Laragon

  1. Install Laragon and check PHP

    Download Laragon from laragon.org and install it in C:\laragon. Open Menu → PHP → Version: Stocky needs PHP 8.2 or newer. If only an older one is listed, download a PHP 8.2+ build (VS16 x64 Thread Safe ZIP) from windows.php.net, unzip it into its own folder under C:\laragon\bin\php\, and pick it in the same menu.

  2. Enable the extensions

    Menu → PHP → Extensions. Make sure curl, fileinfo, gd, mbstring, openssl, pdo_mysql and zip are ticked. Laragon restarts Apache on its own after each change.

  3. Copy the files

    Unzip Stocky into C:\laragon\www\stocky, so that C:\laragon\www\stocky\public exists — not C:\laragon\www\stocky\stocky\public. The folder name becomes the local address.

  4. Start and get the address

    Run Laragon as administrator the first time (it needs to write the Windows hosts file) and press Start All. With Menu → Preferences → General → Auto create virtual hosts ticked (the default), Laragon creates http://stocky.test and points it at the public/ folder. If the address does not open, press Reload in Laragon.

  5. Create the database

    Press Database in Laragon to open HeidiSQL and connect with user root and an empty password. Right-click the connection → Create new → Database, name it stocky, collation utf8mb4_unicode_ci.

  6. Run the installer

    Open http://stocky.test/setup and follow the four steps. Application URL: http://stocky.test. Database: host 127.0.0.1, port 3306, database stocky, user root, password empty.

XAMPP

  1. Install XAMPP

    Download the PHP 8.2 or newer build of XAMPP from apachefriends.org and install it in C:\xampp. Open the XAMPP Control Panel and start Apache and MySQL.

  2. Enable the extensions

    Control Panel → Apache Config → PHP (php.ini). Remove the leading ; from any of these lines that still have one, raise the two limits, save, then Stop and Start Apache:

    extension=curl
    extension=fileinfo
    extension=gd
    extension=mbstring
    extension=openssl
    extension=pdo_mysql
    extension=zip
    
    max_execution_time=300
    memory_limit=512M
  3. Copy the files

    Unzip Stocky into C:\xampp\htdocs\stocky, so that C:\xampp\htdocs\stocky\public exists.

  4. Add a virtual host

    XAMPP does not create local domains. Open C:\xampp\apache\conf\extra\httpd-vhosts.conf in a text editor and add at the end:

    <VirtualHost *:80>
        ServerName localhost
        DocumentRoot "C:/xampp/htdocs"
    </VirtualHost>
    
    <VirtualHost *:80>
        ServerName stocky.test
        DocumentRoot "C:/xampp/htdocs/stocky/public"
        <Directory "C:/xampp/htdocs/stocky/public">
            AllowOverride All
            Require all granted
        </Directory>
    </VirtualHost>

    The first block keeps http://localhost and phpMyAdmin working. Then open Notepad as administrator, open C:\Windows\System32\drivers\etc\hosts, add the line below, save, and restart Apache:

    127.0.0.1    stocky.test
  5. Create the database

    Open http://localhost/phpmyadmin → Databases. Name stocky, collation utf8mb4_unicode_ci, Create.

  6. Run the installer

    Open http://stocky.test/setup and follow the four steps. Application URL: http://stocky.test. Database: host 127.0.0.1, port 3306, database stocky, user root, password empty.

Check XAMPP's database version. XAMPP bundles MariaDB, and recent builds still ship MariaDB 10.4 — older than the MariaDB 10.6 in the requirements. phpMyAdmin shows the version on its home page. If the install stops on a database error, use Laragon (MySQL 8) instead.

Use a domain, not a sub-folder. Open Stocky at http://stocky.test, not http://localhost/stocky. Stocky expects to sit at the root of its own address; under a sub-folder, links and the admin screens can break.

Common local problems

What you seeWhat to do
Apache will not startPort 80 is taken — usually by IIS, Skype or another web server. Stop that program, or the World Wide Web Publishing Service in Windows Services.
MySQL will not startPort 3306 is taken by another MySQL. Run Laragon or XAMPP, never both at once.
stocky.test does not openThe hosts line is missing — it must be saved by an editor running as administrator. On Laragon, run it as administrator and press Reload.
The page lists files, or shows the XAMPP dashboardThe address is not pointing at public/. Check the DocumentRoot in the virtual host, then restart Apache.
Images or styles do not load after the installThe application URL in .env (APP_URL) does not match the address in the browser. Make them identical, including http or https.
Camera scanner or PWA install is missingBrowsers only allow them on https:// or on http://localhost. On Laragon, turn on Menu → Apache → SSL → Enabled and use https://stocky.test, with APP_URL changed to match.

Scheduled tasks are optional on a local install; if you want them, see Cron & queue — on Windows they run from Task Scheduler. To move a local install to a live server later, export the database, upload the files and the public/images folder, import the database there, and change APP_URL and APP_DEBUG=false in .env.

Updating

Settings → Update. Three tabs: Automatic Update, Manual Update and the Update Guide. The installed version is shown against the latest one published on the update server.

/next/settings/update
Update settings
Automatic update: upload the ZIP, pass the pre-update checks, install. The history and the update backups sit below.

Automatic update

Only available from version 5.8. The automatic updater ships with version 5.8. If you are on an older version, use the manual update to reach 5.8 first; after that, every later update can be installed from this page.

  1. Back up

    The updater takes its own backup of the files and the database, but take a database backup of your own first anyway.

  2. Upload the ZIP

    Download the new version from CodeCanyon and drop the full application ZIP onto the page. Nothing is touched yet: the pre-update checks validate the archive, its structure, the version, PHP requirements, permissions, disk space and the database connection.

  3. Install

    Press Install. Stocky backs up the files and the database to storage/app/updater/backups, puts the site into maintenance mode, replaces the files, runs the migrations and permission sync, and comes back. Keep the tab open; a bypass link is shown in case you lose the page.

  4. Reload

    Hard-refresh the browser (Ctrl + Shift + R) so it loads the new admin files. Check the version number in the footer.

If anything fails the previous version is restored automatically. If the rollback itself cannot finish, the page says Recovery required and offers Open Recovery Console — a standalone page at /system-update/recovery that works even in maintenance mode, where you can continue where it stopped, roll back, or discard the run. The pre-update backup stays intact until you resolve it. Update backups keeps the last few (three by default); the only remaining complete one can never be deleted.

Manual update

For hosts where the automatic updater cannot write, or if you prefer to see each step. The Manual Update tab describes it; in short:

  1. Back up the database and the public/images and storage/app folders.
  2. Upload the new files over the old ones. Do not delete or replace your .env file, the public/images/ folder or the storage/ folder — they hold your configuration, uploaded images and generated files, and removing them would break the installation and lose your data.
  3. Open https://your-domain/update.
  4. Hard-refresh the browser.

Custom work is overwritten by an update. If you or a developer have customized any files, those changes will be lost when you update.

Your first hour

A fresh install already knows the shape of a shop — it has a default warehouse, a walk-in customer, a set of payment methods and a currency. This is the shortest route from there to a counter that sells.

  1. Company details

    Settings → System Settings. Company name, logo, phone, email and address print on every receipt and invoice. Set the default currency, the timezone, the date and price formats, and the default warehouse and customer the POS opens with.

  2. Warehouses

    Settings → Warehouses. One is enough. Add one per shop, store-room or van if stock physically lives in different places — every stock figure is per warehouse, and users can be limited to the warehouses they may see.

  3. Categories, brands and units

    Products → Categories / Brand / Units. Short lists you edit rarely. Units can convert (a carton of 12 pieces); categories can carry an icon and an image for the POS tiles and the store.

  4. Products

    Products → Create product for a few, Import products for a spreadsheet. A product needs a name, a code, a category, a unit, a cost and a price; everything else — barcode symbology, tax, images, variants, stock alerts — can come later.

  5. Opening stock

    Products → Opening Stock imports a quantity per product per warehouse. Or receive your first purchase, which is the honest way to start a stock figure with a cost behind it.

  6. Payment methods

    Settings → Payment Methods. Cash, card, bank transfer and so on are seeded; hide the ones you do not take. Add a cash account under Accounting → List accounts if you want payments to land in named accounts.

  7. The receipt

    Settings → POS Receipt. Pick the paper width (58 or 80 mm), one of the five layouts, and what prints on it — the preview on the right is live. Settings → POS Settings holds the rest: auto-print, hold sales, the cash drawer and keyboard shortcuts.

  8. Users

    User Management → Group Permissions to create a Cashier role with only the POS and sales permissions, then Users to add each person with that role and the warehouses they may see.

  9. Open the POS and sell something

    Press the purple POS button in the header. Open the register with a float, pick the warehouse, tap or scan a product, Pay Now, cash, Complete Payment. The receipt prints; the stock moved.

Everything else — the online store, accounting, HRM, the marketplaces, the business modules — can wait. Turn off what you do not use in Settings → Modules so the sidebar shows only what your business runs.

Demo catalogues

Four seeders fill the store with a themed catalogue, complete with pictures, so you can see a theme with real products before entering your own. Each one switches the store to its theme and is safe to run more than once:

php artisan db:seed --class=ElectronicsDemoSeeder
php artisan db:seed --class=ToysDemoSeeder
php artisan db:seed --class=GroceryDemoSeeder
php artisan db:seed --class=RealEstateDemoSeeder

For a general set of customers, suppliers, products, sales, purchases, quotations and expenses without any theme, use the demo-data generator in Settings → System Settings — it works from the panel and needs no shell.

Demo data is a lot to delete afterwards. Seed it on a test install, not on the database you will trade with.

Around the screen

A few things sit outside the modules and are worth knowing before you start.

WhereWhat it does
POS, the purple button in the headerOpens the register full-screen. It is its own application: the sidebar disappears and comes back when you leave.
Today's summary, the pie-chart iconA drawer with today's sales, payments and stock alerts without leaving the page you are on.
Light / dark, the bulbFlips the theme for your browser. The customiser (below) also offers auto, which follows the operating system.
Full screenHides the browser chrome for a till or a wall-mounted screen.
Language, the globeSwitches the whole panel to any language enabled in Settings → Languages. Arabic flips the layout right-to-left.
The bellIn-app notifications — stock alerts, new online orders, kitchen tickets, sync results — newest first, with the unread count on the badge.
The user menuYour profile (name, email, password, avatar) and sign out.
The gear, bottom rightThe appearance customiser: sidebar layout (default, large, flat or dark), theme mode and colours. Saved for your browser; it changes nothing for anybody else.
Install appOn HTTPS, an Install App button appears in the header and installs the admin as a PWA on a desktop or a phone. The POS, the store, the customer display and the portal each have their own manifest.
/next/dashboard · dark
Dashboard in the dark theme
The dark theme, from the user menu.
/next/dashboard · العربية
Dashboard in Arabic, right-to-left
Arabic: the whole panel runs right-to-left.

The sidebar shows only the modules that are switched on and only the pages your role may open. A cashier with POS-only permissions sees a very short sidebar; that is by design. The version number in the bottom corner is what Settings → Update compares against the update server.

Dashboard on a phone
The admin on a phone.
Sales list on a phone
Lists collapse into cards.
POS on a phone
The register on a phone.

System settings

Settings → System Settings. The one page nearly every other screen reads from. It is split into tabs; each saves only its own fields.

/next/settings/system
System settings
Company details, defaults and formats. The logo set here prints on receipts, invoices and PDFs.
TabWhat lives there
CompanyName, logo, phone, email and address. Sidebar logo size. The footer line and the developed by credit.
SystemDefault currency, default language, timezone, date format and price format. Default warehouse, default customer, default payment method, default account and default tax for new documents. The offline sync switch for the POS (see Offline mode). The default dashboard date range and widget order.
SalesHow sales documents behave: the sales agent field, credit limits, minimum prices and the loyalty point-to-amount rate.
DashboardFont family and size; table density, striped rows, cell borders, sortable columns and column visibility — the feel of every list. Which dashboard widgets show and in what order.
Export, CalendarDefaults for Excel and PDF exports; Google Calendar credentials for the bookings module.
Features, Security, BackupThe feature switches, login-device rules and the cloud backup target (S3 or Google Drive) — the same forms as the dedicated pages under Settings.
POS Settings, POS Receipt, Payment Gateway, ZATCAShortcuts to those settings pages so the whole configuration is reachable from one place.
Demo dataThe generator described under Demo catalogues: customers, suppliers, products, sales, purchases, quotations and expenses, with a status line showing what is already in the database.

The timezone decides which day an evening sale belongs to and when the scheduled jobs run. The default currency is the base currency for every report and stock valuation — if you turn on multi-currency later, other currencies convert into this one. Set both before you trade.

Feature switches

Settings → Modules → Features (the same switches are on the Features tab of System Settings). These change how the whole system behaves, so they live together rather than hidden in the module they affect.

/next/settings/business-modules · Features
Feature switches
Each switch carries its own explanation. Press Submit after changing them.
SwitchWhat it does
3-decimal pricingPrices, costs, discounts, taxes and POS totals keep three decimals (0.066) instead of rounding to two. For currencies such as the dinar.
Kitchen displayThe POS shows Send to Kitchen / Save without sending / Send later and the Kitchen Display page appears. Also sets the preparation-time target and whether confirmed store orders create a ticket automatically.
Show barcode (GTIN)Shows the GTIN / UPC / EAN / ISBN field on the product form, separate from your own product code.
Resize product imagesDownscales uploads to the max size (default 800 px on the longest edge). Turn off to keep originals — larger files, slower pages.
Serial number / IMEI trackingLets a product require a unique serial per unit, captured at purchase and picked at sale. See Serial numbers.
Multi-pack sellingA product can be sold as single, 6-pack or case, each with its own price, while stock stays in one base unit.
Wholesale pricing by quantityProducts carry quantity breaks (10–19, 20–49, 100+) that replace the retail price in the POS and the store once the ordered quantity reaches a tier. Turning it off keeps the tiers but stops applying them.
Multi-currencyRecord sales, purchases and online orders in other currencies with manual exchange rates. Reports and stock stay in the base currency. See Multi-currency.
Change salesperson during checkoutA salesperson picker on the POS so a sale can be credited to another employee without logging out; the choice is saved on the invoice and used in the seller report.
Auto journal entriesPost an accounting journal automatically when a sale, purchase, expense, return or payment is recorded. See Accounting.

Business modules

Settings → Modules. Twenty-three optional modules, each with its own menu group, pages, permissions and reports. Switch off what your business does not do and the sidebar shrinks to match. Core commerce — products, sales, purchases, people, settings and reports — cannot be turned off.

/next/settings/business-modules
Business modules switches
Store, HRM, recruitment, meetings, marketing, accounting, e-wallet, commissions, promotions, WooCommerce, Shopify, Salla, Jumia, documents, subscriptions, manufacturing, assets, projects, bookings, service, fleet, hospital and school.

A module that is off is also off for the router: its pages answer not found even by direct address, and its permissions disappear from the role editor. Turning it back on restores everything — no data is deleted by the switch.

Settings → Module Settings is a different page: it lists add-on modules installed as packages and offers Upload Module for a ZIP supplied by the vendor. A fresh install lists none.

Warehouses & locations

Settings → Warehouses. A warehouse is any place stock physically lives: a shop, a stockroom, a van, a market stall. Every stock quantity, every alert and every sale, purchase, transfer and adjustment is tied to one.

/next/warehouses
Warehouses list
Warehouses with their contact details. Rack locations are the second tab.

Internal locations

The Locations tab holds aisle, rack and bin positions inside a warehouse. Products can be assigned to a location so the picker knows where to walk; the Internal Location report lists what sits where.

Who sees which warehouse

Each user is assigned the warehouses they may work in (User Management → Users). The POS, the lists and the reports then only offer those. A cashier in the downtown shop never sees the airport store's stock; a manager assigned to all of them can switch. The default warehouse from System Settings is where the POS opens.

Users & roles

User Management → Users. A user is anyone who signs in to the admin or the POS. Each has a role, a status (inactive users cannot sign in but keep their history), an avatar and the warehouses they may see.

/next/users
Users list
Users with role and status.
/next/users/create
Add user form
Adding a user: role, password, warehouses.

The install ships one role, Owner, which holds every permission — the administrator account has it. Create a role per job, not per person: Cashier, Stock keeper, Accountant, Store manager. Then give people the role.

Users can be signed out remotely from Settings → Login Devices, and every sign-in is listed in the Login Activity report.

Permissions

User Management → Group Permissions. A role is a named set of permissions. The editor lists more than 300 of them, grouped by module, with a search box and a select-all per group.

/next/permissions/create
The role editor
Creating a role. Groups follow the sidebar; a module that is switched off does not appear.

Most groups follow the same pattern — View, Create, Edit, Delete — with extras where a module has a sensitive action: override FEFO / sell quarantined under batches, write off, Pay due, report-level permissions, and the settings pages one by one, so a manager can be given POS Settings without Payment Gateway.

A cashier role

The minimum for somebody who only runs the till: POS, Sales → View and Create, Customers → View and Create (for quick-add at the counter), and nothing under Settings, Purchases or Reports. Add Sales → Edit only if they should be able to change a completed sale, and Cash Register Report if they close their own drawer.

Permissions apply to the API as well as the menu. A page hidden from the sidebar is also refused when typed into the address bar, and the mobile app sees the same set.

Categories, brands, units & currencies

Short reference lists under Products and Settings. Get them roughly right before importing products, because the import matches on their names.

/next/categories
Categories
Categories carry a code, an icon and an image for the POS tiles and the store.
/next/units
Units
Units and their conversions.
ListNotes
Categories and Sub-categoriesTwo levels. The POS filters by category; the store builds its menus and filters from them; kitchen stations claim categories.
BrandsA name and a logo. The POS has a brand filter; the Electronics theme shows a brand row.
UnitsA base unit (piece, kg, litre) and derived units with an operator and a value — a carton is × 12 pieces. Products have a stock unit, a purchase unit and a sale unit, so you can buy by the carton and sell by the piece.
Size guidesTables (S/M/L with measurements) attached to products and shown on the store's product page.
Vehicle fitmentMakes, models and years a part fits. The store lets a shopper pick their vehicle and filters the catalogue to what fits.
Currencies (Settings → Currencies)Code, symbol and — with multi-currency on — an exchange rate against the base currency. The store's currency switcher offers whichever you enable.

Payment methods & accounts

Settings → Payment Methods. The ways money arrives: the install seeds Cash, Credit Card, Check, TPE, Western Union, bank transfer and other. Rename, add or deactivate them; the POS payment screen and every payment form offer the active ones. Store credit and wallet are handled by the e-wallet module.

/next/settings/payment-methods
Payment methods
Payment methods. Each can be switched off without deleting the payments already recorded with it.

Accounts (Accounting → List accounts) are where the money is kept: the till, the bank account, the mobile-money float. Every payment, deposit and expense may name an account, and the account balance moves with it. The default account in System Settings is pre-selected on new payments. See Accounts, deposits & expenses.

Payment gateways are separate: Settings → Payment Gateway holds the Stripe keys the POS uses for card payments; the online store's twelve gateways are under Store → Payment Gateway.

Products

Products → All Products. The catalogue. One row per product with its image, code, category, brand, cost, price, unit and the stock across the warehouses you may see. The list filters by warehouse, category and brand, exports to Excel and PDF, and opens the Print Labels sheet for any selection.

/next/products
Products list
The product list. Quantity is per warehouse; the total is what you may see.

The product form

/next/products/create
Create product form
Creating a product. The type at the top decides which panels appear below.
Field groupWhat to put there
IdentityName, code (generated if you leave it blank), barcode symbology (Code 128, EAN-13, UPC-A, …), optional GTIN, brand, category and sub-category.
UnitsThe stock unit, and optionally different purchase and sale units with a conversion.
MoneyCost, price, tax rate with inclusive or exclusive, and a default discount. With the wholesale switch on, a table of quantity tiers; with multi-pack on, the pack sizes and prices.
StockThe stock alert quantity, opening stock per warehouse, an internal location, and whether the product tracks batches or serial numbers.
Media & textImages (upload or paste a hosted URL), a note, a warranty period, a size guide, vehicle fitment, and any custom fields defined in Settings → Custom Fields.
Online storeWhether the product is visible in the store, the collections it belongs to, the storefront description and SEO text, pre-order and quote-request options.

The product page

/next/products/1
Product details page
A product's detail page: stock per warehouse, movement history, sales and purchases.

Every product has a detail page with its stock per warehouse, a movement history — every sale, purchase, return, transfer and adjustment that touched it, in order — and the sales and purchase lines it appeared on. The Product Report under Reports is the same view with a date range and export.

Variants, combos & services

The type at the top of the product form decides how stock behaves.

Single

One code, one price, one stock figure per warehouse. Most products.

Variable

A parent with variants — size, colour, capacity. Each variant has its own code, price, cost, image and stock. The POS and the store show the parent and let you pick the variant.

Service

No stock at all. Repairs, delivery, labour, consultations. Can carry a price and a tax like any product; the store can offer request a quote instead of a price.

Combo

A bundle sold as one line at one price. Selling it deducts each component's stock; the combo itself has none.

Subscription products (their own module, see Subscriptions) add a billing cycle to any product. Packs and wholesale tiers are pricing on top of a single or variable product, switched on under Feature switches.

Importing

Every import page has the same shape: a drop zone, a Download example button that gives you a template with the right columns, a table explaining each column and which are required, and Import now. Rows that fail are reported by line number; rows that pass are saved.

/next/products/import
Import products page
Import products: one tab per product type, and the expected format underneath.
ImportWhereNotes
ProductsProducts → Import productsThree tabs — single, variant and service products — each with its own template (.xlsx). Category, brand and unit are matched by name and created when missing.
Products, update onlyProducts → Import (Update Only)Matches existing products by code and patches price, cost and stock. Never creates a product — safe for a supplier price list.
Opening stockProducts → Opening StockCode, warehouse and quantity, for single products and for variants. Recorded as an opening adjustment so the movement history starts cleanly.
Customers, suppliersPeople → Import Customers / Import SuppliersName, email, phone, address, tax number, opening balance.
Sales, purchasesSales → Import Sales, Purchases → Import PurchasesCSV with one row per line item; the reference groups rows into a document. For migrating history from another system.
/next/products/opening-stock-import
Opening stock import
Opening stock per warehouse.

Import in this order: categories, brands and units by hand; then products; then opening stock; then customers and suppliers; then history if you want it. Product codes must be unique — a duplicate code is the most common rejected row.

Barcode labels

Products → Print Labels. Pick products (or a whole purchase), set a quantity per product, choose one of the five label templates and what prints on it — shop name, product name, price, barcode number — and print. The preview is true to size.

/next/products/barcode
Print barcode labels
Label printing with a live, true-size preview. Settings such as fonts and barcode height are saved globally.

Labels go to a normal printer as a sheet, or directly — no print dialog — to a TSPL label printer over USB or the network. Products without a barcode of their own are printed with their product code, which the POS scanner reads just the same.

Batches & expiry

For food, pharmacy, cosmetics and anything with a shelf life. Turn batch tracking on per product; from then on every purchase line asks for a batch number and an expiry date, and stock is kept per batch.

/next/products/batches
Batch register
The batch register: quantity on hand, expiry and status per batch and warehouse.

Sales allocate first-expiry-first-out: the POS takes from the batch that expires soonest. Expired or quarantined batches are skipped unless the user holds the override FEFO / sell quarantined permission. Batches can be written off, and the Expiry report lists what expires in the coming days by warehouse; the Batch Register and Batch History reports show where each batch went.

/next/reports/expiry
Expiry report
The expiry report.

Serial numbers

With the Track serial number / IMEI switch on (Feature switches) a product can require one serial per unit. Receiving a purchase asks for the serials; selling asks you to pick which units leave; returns bring a specific unit back. Phones, laptops, appliances, tools with a warranty.

/next/serial-numbers
Serial numbers register
Every serial with its status — available, sold, returned — and the documents it passed through.

Four reports cover them: Available Serial Numbers, Sold Serial Numbers, Serial Movement Log and Product Serial Inventory. The Warranty & Guarantee report combines the serial with the product's warranty period to show what is still covered.

Count, adjust, transfer, damage

Four operations move stock without a sale or a purchase. Each is a document with a date, a warehouse, lines and a note, and each shows up in the product's movement history and in its own report.

/next/products/count-stock
Count stock
Count stock: a sheet per warehouse and category to count against.
/next/adjustments/create
Create adjustment
An adjustment: add or subtract per line, with a reason.
OperationWhereWhat it does
Count stockProducts → Count StockGenerates a downloadable count sheet for a warehouse (and optionally a category) with the system quantity on a given date, to be counted on paper or a tablet. Enter the differences as an adjustment.
AdjustmentStock AdjustmentAdds or subtracts a quantity per product with a reason: found, lost, sample, correction. The Stock Adjustment report totals them.
TransferStock TransfersMoves quantities from one warehouse to another, with a status (pending, sent, completed) and an optional shipping cost. Stock leaves the source at once and arrives when completed.
DamageDamagesWrites off broken or unsellable units with a note and a value, so the loss is visible in the reports rather than hidden in an adjustment.
/next/transfers/create
Create transfer
A transfer between two warehouses.
/next/damages
Damages list
Damages, with the value written off.

The Negative Stock, Quantity Alerts, Dead Stock, Zero Sales, Stock Aging and Inventory Valuation reports are the places to look for what needs counting, reordering or clearing.

The register

The purple POS button in the header opens the register full-screen. It is built for a touch screen and a scanner: large product tiles with image, code, stock and price; category and brand filters; a search box that also takes a scanner; and a cart on the left with a running total.

/next/pos
The point of sale
The register: the register status and warehouse at the top, the cart on the left, the catalogue on the right, and the status pill bottom left.

Opening the register

With registers enabled, the top-left pill reads CLOSED until you open one. Press it, enter the opening float, and the register is yours for the shift. Every sale, payment and hold is stamped with the register and the cashier. At the end of the shift press the pill again, enter the counted cash and a closing note, and the Cash Register report shows the float, the cash sales, the counted amount and the difference — per register and per cashier.

Warehouse and customer

The warehouse chip picks which stock you are selling from — the POS opens on the default warehouse from System Settings, limited to the warehouses your user may see. The customer chip defaults to walk-in-customer; search for a named customer to attach the sale to their ledger and their loyalty points, or press the person-plus icon to create one without leaving the screen.

Building the cart

/next/pos · العربية
The POS in Arabic
The register in Arabic, fully right-to-left.
/next/real-time-sales-counter
Real-time sales counter
The real-time sales counter: a live board of today's sales that pings when a new one lands.

Live sales counter

Sales → Real-time Sales Counter is a board for a back-office screen: the count and value of today's sales, refreshed by polling every few seconds with a chime when a new sale arrives. It needs no websocket server.

Taking payment

Pay Now opens the payment screen. The total is pre-filled; pick a method and press Complete Payment, or split it.

/next/pos · Pay Now
POS payment screen
Payment: amount, account, method, quick-cash buttons, and Add Payment Method to split.

Completing the payment saves the sale, moves the stock, posts the journal (if auto journals are on), credits the loyalty points, prints the receipt (if auto-print is on) and, if a cash drawer is configured, kicks it open.

POS settings & receipts

Settings → POS Settings decides how the register behaves; Settings → POS Receipt decides what it prints.

/next/settings/pos
POS settings
POS settings: printing, hold sales, the cash drawer, shortcuts and the register.
SettingWhat it does
Invoice formatThermal prints the receipt layout on roll paper; A4 prints the full invoice.
Auto-print receiptPrints as soon as a sale completes instead of waiting for the button.
Enable hold salesShows or hides the Hold button and the drafts list.
Cash drawer auto-openWhen a sale completes with cash, sends an ESC/POS pulse to the receipt printer named here, which kicks the drawer connected to it. Requires QZ Tray running on the cashier's computer.
Direct network printingSends receipts straight to a printer at an IP address and port (usually 9100), bypassing the browser dialog. Good for a tablet till with a shared printer.
Barcode scanning soundA beep on every successful scan.
Products per page, show categoriesHow many tiles load at once and whether the category filter appears.
Keyboard shortcutsThe switch and the cheat sheet — see Keyboard shortcuts.

The receipt

/next/settings/pos-receipt
POS receipt settings with live preview
Five receipt layouts with a live preview. Every change on the left redraws the receipt on the right.

Paper size (58, 80 or 88 mm); one of five layouts — Standard, Compact, Detailed, Bilingual and Minimal; logo and its size; font family and size; and which blocks print: the customer, the tax breakdown, the previous dues and net balance, a note to the customer, and — with ZATCA phase 1 on — the QR code Saudi receipts require. The Bilingual layout prints each label in two languages, for Arabic and English receipts.

Printing

MethodWhen to use it
Browser printThe default. Works with any printer the operating system knows; the dialog appears each time unless the browser is set to skip it.
QZ TrayA small free program on the cashier's computer. Prints silently, raw ESC/POS, and kicks the drawer. Install it, allow the site once, and set the printer name in POS Settings.
Network printerA receipt printer with an Ethernet or Wi-Fi port. The server sends the job directly; nothing to install on the till. The server must be able to reach the printer's IP.
Label printerTSPL printers over USB or the network take the barcode sheets without a dialog.

Keyboard shortcuts

Turn them on in Settings → POS Settings; the switch is per device and saves as soon as you flip it, so a touch till can leave them off while the counter PC has them on. Press Shift + ? on the register for the cheat sheet; the same list is under View Shortcuts in POS Settings.

The shortcuts cover what a cashier does a hundred times a day: focus the search or scan box, open the payment screen, complete a cash payment, hold the sale, open the drafts, clear the cart, change the customer, open the drawer and close the register. They are ignored while you are typing in a form field, except the function keys and Esc, so a barcode typed by a scanner is never misread as a command.

Offline mode

The register keeps selling when the internet does not. Switch it on with offline sync in Settings → System Settings → System.

  1. The register caches

    While online, the POS keeps a copy of the catalogue and the customers in the browser, and refreshes it as you work. The status pill bottom left reads Online · synced.

  2. The connection drops

    The pill turns red and reads Offline. Tiles, search, the cart, holds and drafts keep working from the cache. Sales you complete are queued in the browser with their payments, and the pill shows how many are waiting. Reloading the page while offline is fine — the register comes back from the cache.

  3. It comes back

    The queue uploads itself, oldest first; each sale gets its reference and moves the stock as if it had been taken online. The pill returns to Online · synced. If a queued sale is refused — a product deleted meanwhile, say — it stays in the queue with the error so nothing is silently lost.

What offline cannot do. Opening or closing the register, card payments through Stripe, kitchen tickets, customer-display updates and anything that needs the server to answer. Stock figures on the tiles are as of the last sync, so two offline tills can both sell the last unit. The queue lives in that browser's storage — do not clear site data while sales are waiting.

Customer display

A second screen facing the customer — a tablet on a stand, a monitor, an old phone — that mirrors the cart as the cashier works: the lines, the totals, and a thank-you when the sale completes. It is a web page, so any device with a browser on the same network will do.

/next/customer-display/setup
Customer display setup
Sales → Customer Screen: generate a token, then open the URL or scan the QR code on the second device.
  1. Generate a token

    Sales → Customer Screen → Generate New Token. The page shows the display URL — /customer-display?token=… — and a QR code for it.

  2. Open it on the display device

    Scan the QR or type the URL. The page installs as a PWA and runs full-screen. It supports light and dark themes and needs no login — the token is the credential.

  3. Sell

    The display updates as items are added. Tokens expire after 24 hours; generate a new one to rotate access, and the old link stops working at once.

/customer-display?token=…
The customer display
What the customer sees.

If the display does not connect, check that the device is on the same network and uses the full URL including the token. If items stop updating, make sure the POS is still open on the cashier's side — the display shows the last cart the register broadcast.

Kitchen display

For restaurants, cafés and anywhere an order is prepared after it is taken. Switch it on under Feature switches; the POS then offers Send to Kitchen on every sale and Kitchen → Kitchen Display appears in the sidebar.

/next/kitchen-display
Kitchen display
Tickets in lanes — open, preparing, ready — with the daily token number, the elapsed time and per-item check-off.

The order-ready screen

A customer-facing board of token numbers under Preparing and Ready, with a chime when one moves. Press Order Ready Screen on the kitchen display to generate a secure link (/order-ready?token=…), open it on a screen in the collection area, and it updates on its own. The link stays valid for seven days; generating a new one replaces it.

/next/kitchen/report
Kitchen report
The kitchen report: preparation and wait times, staff performance, trends and top products, with export.

Sales

Sales → All Sales. Every invoice, from the POS or from the back office, in one list: date, reference, customer, warehouse, status, grand total, paid, due, payment status and shipping status. Filter by any of them, export, and act from the row — Pay due, print, PDF, email, SMS, edit, return, delete.

/next/sales
Sales list
The sales list with status and payment status pills.

Creating a sale in the back office

/next/sales/create
Create sale form
The sale form: the same lines as the POS, with a status, a sales agent, a note and attachments.

The form is the POS in a page: customer, warehouse, date, lines with discount, tax, unit and batch or serial, an order tax, discount and shipping, a status (pending, ordered, complete), a sales agent, a note, and a payment you can record at once. Stock moves when the sale is completed. With multi-currency on, pick the sale currency and the base-currency equivalent shows alongside.

The sale page

/next/sales/227
Sale detail page
A sale: lines, totals, payments, shipment and documents, with the print, PDF, email and SMS buttons.

Payments are recorded against the sale with a date, a method and an account; each one updates the paid and due figures and the customer's ledger. Attach a file — a signed delivery note, a purchase order from the customer — under documents. Email and SMS use the templates from Settings, merged with the sale.

Quotations

Quotations. A priced offer that moves no stock. Same form as a sale; same lines; a status of pending or sent. Print or PDF it, email it, and when the customer agrees press Create sale — the quotation's lines become a sale in one click, and the quotation is marked as converted.

/next/quotations
Quotations list
Quotations.
/next/quotations/30
Quotation detail
A quotation, ready to convert.

Business customers can also see their quotations in the client portal, accept them there, or request a new one; shoppers can send a quote request from the store for service products.

Returns

A return is always against an original document, so the stock, the money and the reports agree on what came back.

/next/sale-returns
Sale returns
Sale returns.
/next/purchase-returns
Purchase returns
Purchase returns.

The Return Ratio report shows what comes back most, by product and by customer.

Shipments

Sales → Shipments. One shipment per sale that needs delivering: the carrier, a tracking number, the delivery address and a status — packed, shipped, delivered, cancelled. The shipping status shows on the sale and on the sales list, and the store's customer account shows it to the shopper.

/next/shipments
Shipments list
Shipments and their status.

To hand the parcel to a courier company, print its label and have the status follow by itself, use Couriers; those shipments are listed here as well.

Suppliers & purchases

People → Suppliers holds who you buy from — name, contact, tax number, address, opening balance — with a detail page listing every purchase, return and payment. Purchases is how stock arrives with a cost behind it.

/next/suppliers
Suppliers list
Suppliers.
/next/purchases
Purchases list
Purchases with status and payment status.

Receiving a purchase

/next/purchases/create
Create purchase form
A purchase: supplier, warehouse, lines with cost, batch and expiry, and the payment.

Supplier, warehouse, date, lines with the unit cost, the purchase unit, a discount and a tax; per line a batch number and expiry for batch products and the serials for serial products; an order tax, discount and shipping. The status is pending, ordered or received — stock moves when it is received. Record the supplier payment at once or later from the row. A purchase can also open the label printer for everything it contains.

/next/purchases/180
Purchase detail
A purchase with its lines, payments and documents.

The product's cost is what you paid; Inventory Valuation uses it, and the profit reports subtract it from the sale price. Purchases can be imported from CSV to bring in history; see Importing.

Couriers: how it works

Couriers in the sidebar. Send a sale to a courier company in one click, print its label, and let the courier's own updates — picked up, out for delivery, delivered, returned, cash collected and paid out — arrive in Stocky by themselves. Forty couriers are built in, from Pakistan, the Gulf, Egypt, Bangladesh, India and Southeast Asia to DHL, FedEx and UPS, plus shipping aggregators that reach hundreds more and a manual courier for anyone without an API.

Book

From a sale, the sales list (one or many at once) or the sale page. The form fills itself from the order: receiver, address, COD amount, weight. Aggregators and global couriers show live prices to pick from.

Track

Couriers that can push send each change to Stocky the moment it happens; the rest are checked on a schedule you choose. Every update lands on the shipment's timeline and the sale's shipping status.

Settle

Delivered COD parcels are marked collected; when the courier pays you out, the payment is recorded on the sale. Courier charges can be saved as expenses, and returned parcels go to a review queue or straight back into stock.

Keep customers posted

SMS, email or WhatsApp messages at the statuses you pick, and a public tracking page in your online store where customers follow their parcel.

Measure

A courier report with delivery and return rates, COD and charges by courier and by city, and a return-risk badge on customers who often send parcels back.

Any courier

No API? Add it as Manual / Other courier and type the tracking number, or use AfterShip or 17TRACK so the status follows by itself for thousands of carriers.

The sidebar group has six pages: Courier Shipments, Courier report, Courier Accounts, Courier Settings, Courier logs and Courier guide. The sale page gains a Courier shipment panel, and the sales list a Send to courier action.

Courier guide is the in-app companion to this chapter: a checklist that shows how far your setup has gone, with a link for each step, a picker that shows any courier's keys, options, how its updates arrive and what to watch for, with an Add this courier button, and your accounts' webhook addresses with copy buttons.

Switching it on and who can use it

Couriers is a business module, Courier Integration: switch it off in Settings → Modules to hide the sidebar group, the sale page panel and the Send to courier actions. Four permissions, in the Couriers group of the role editor, decide who does what:

PermissionAllows
Manage courier accounts and settingsCourier Accounts and Courier Settings.
Book, cancel and print courier shipmentsSend to courier, cancel a booking, print labels.
View courier shipments, COD and returnsCourier Shipments, the sale's courier panel, status and COD updates, the returns queue.
Courier reportThe courier report. Roles that could see courier shipments receive it automatically.

Courier accounts

Couriers → Courier Accounts lists your accounts with their connection state — Connected, Failed or Not tested — the warehouses they serve and which one is the default. You can hold several accounts for the same courier, for example one per warehouse or one per city.

  1. Choose the courier

    Add courier account, then pick the courier from the catalogue. Each card shows the courier's region and what it does — booking, labels, live rates, cancellation, status pushes, COD, city lists, pickup requests, test mode.

  2. Paste the API credentials

    Each courier asks for its own keys; the help under every field says where to find them, and Courier-by-courier setup sums them up. Saved secrets are never shown again: leave a field blank to keep the stored value.

  3. Test mode or live

    Couriers that offer a sandbox have a Mode switch. In Test the account talks to the courier's test system — bookings are not real and nobody comes to collect them. Sandbox and live keys are usually different, so paste the matching pair.

  4. Courier options and pickup address

    Courier options are that courier's own settings — a pickup location code, a service, a country. The Pickup address is where parcels are collected; couriers that work with full postal addresses (aggregators, DHL, FedEx, UPS, Ninja Van, Flash Express) also ask for the pickup postal code, state and two-letter country code, and a default parcel size.

  5. Booking defaults

    The warehouses the account serves (orders from those warehouses pick it automatically), a default weight in kg, a service type, and whether customers may open the parcel before paying. Tick Default account for the one used when no warehouse rule applies.

  6. Test the connection

    Save, then Test connection. Many couriers answer with something useful — your pickup addresses, stores, warehouses or package codes with the codes to paste into Courier options.

  7. Register the webhook URL

    Couriers that push status changes show a Webhook URL on the account once it is saved. Paste it in the courier's dashboard — the setup tables say where — so updates arrive instantly. Bosta, Sendbox and UPS Track Alert register it themselves with every parcel. Couriers that sign their updates — AfterShip, EasyPost, Shiprocket, OTO, Biteship, Pathao and Steadfast — also need the webhook secret you set there pasted on the account: until it is, their updates are rejected (Courier logs shows why).

The webhook URL is a secret. It identifies the account, and some couriers send their updates without a signature. Paste it only into that courier's dashboard. It is built from your site's address; if you move Stocky to another domain, update it at the courier.

Manual / Other courier has one extra field, Tracking link: the courier's public tracking page with {tracking} where the number goes, for example https://courier.example/track?id={tracking}. Staff and customers get a working link from it.

Sending orders to a courier

Three ways in: Send to courier in a sale's row menu on the sales list, the button on the sale page's Courier shipment panel, or — for many orders at once — tick sales on the list and press Send to courier (n) in the toolbar.

The booking form

Everything is filled from the sale and can be changed before booking:

The customer's return-risk badge sits next to Receiver; a high-risk customer also gets a red warning above it.

Compare rates

Aggregators (EasyPost, Shippo, Shiprocket, Sendcloud, OTO, Torod, EasyParcel, Biteship, Shiplogic, Sendbox), DHL Express, FedEx, UPS and Lalamove offer Compare rates: prices and delivery days straight from the carriers for this exact parcel. Pick one and Book buys that option. Without a pick, the account's default service is used — or, for DHL, FedEx and UPS with no default, the cheapest quote.

Booking many orders

The bulk window lists every ticked sale as Ready, Incomplete (hover it to see what is missing — a phone, an address, a city) or Already booked. Choose the account, optionally one Weight for all (kg) instead of From products, and press Book n orders. Each order is booked on its own, so one rejection does not stop the rest; the result shows what was booked and why anything failed, with Print labels for the lot.

Labels

Print label prints the courier's own label or airway bill when the courier issues one — a PDF, a link, or for UPS a label image laid out for 4 × 6 paper. Couriers without labels get a Stocky label: 100 × 150 mm with the tracking barcode, sender, receiver and the amount to collect. Allow pop-ups for the Stocky, or the browser blocks the print window.

DHL Express, FedEx and UPS hand the label over only once, when the shipment is created; Stocky keeps it on the shipment, so reprinting is always possible.

Cancelling

Cancel booking works while the shipment is still Booked. Couriers with a cancel call (or UPS's void) are told; for the others, cancel in the courier's portal as well. Once the courier has the parcel it can only come back as a return. A cancelled sale can be sent again, and so can a sale whose parcel came back — the returned parcel keeps its own record and leaves the returns queue as Sent again. Once returned goods were restocked with a sale return, they are back in stock: ship them on a new sale.

Tracking shipments

Couriers → Courier Shipments. Every courier shipment with its tracking number, sale, customer, city, status, COD and return state. The tabs — All, On the way, Returns to review, COD to be paid out and Status check errors — have a counter card each on top; click a card to open its tab. Search by tracking number, sale or customer; filter by account, status or booking dates; tick rows to print their labels together.

The row menu holds the actions: Timeline, Check status now, Open tracking page, Print label, Update status, Update COD, the return actions, Cancel booking and View sale. The same shipment, with its timeline, shows on the sale page.

The statuses

Courier statusMeaningSale's shipping status
BookedThe courier has the order; nobody has collected it yet.Packed
Picked upThe courier collected it.Shipped
In transitMoving between hubs, in customs, held.Shipped
Out for deliveryWith the rider today.Shipped
Delivery attempt failedNot home, refused, wrong address — the courier will try again or return it.Shipped
DeliveredHanded to the customer; COD becomes collected.Delivered
ReturningOn its way back to you.Shipped
ReturnedBack with you; see returns.Cancelled
CancelledThe booking was cancelled.Cancelled

Statuses only move forward, so a late or repeated update never drags a parcel back. The one exception: a delivered parcel can still be reported as returning or returned, when the customer refuses it after hand-over. Each courier's own wording is kept on the timeline next to the status.

Where updates come from

Courier logs

Couriers → Courier logs records every call Stocky makes to a courier — connection tests, bookings, rates, city lists, labels, cancellations, status checks — every update a courier sends, accepted or rejected, and every error. Filter by account, action, result, direction and date, or search inside the content; Details shows what was sent and the courier's exact answer, with a link to the shipment and the sale. It is the first place to look when a test fails, a booking is refused or statuses stop moving.

Keys, tokens and passwords are masked before anything is stored, and long content is shortened. Scheduled status checks are logged only when they fail; Check status now is always logged. Entries are kept 30 days; Clear logs older than 7 days and Delete all logs tidy up sooner. The page needs the Manage courier accounts and settings permission.

COD, charges & returns

Couriers → Courier Settings decides what Stocky does with money and returned parcels. Everything is optional and happens once per shipment, however many times the courier reports the same thing.

Cash on delivery

A COD shipment goes Not collected → Collected by courier (on delivery) → Paid out to you. Couriers that report payouts — PostEx, Leopards, TCS, Trax, M&P, Shiprocket, Pathao, RedX and eCourier — move the last step themselves, with the payout reference; for the others use Update COD.

With Record the payment on the sale when the courier pays out the COD amount on and an Account chosen, a payout is saved as a payment on the sale, into that account, with the payment method you pick — the sale's balance and the account balance follow. Without an account, payouts are only marked.

Courier charges

Save the delivery charges reported by the courier as an expense adds one expense in the chosen category when a shipment is delivered, returned or cancelled, for the charges the courier reported.

Returned parcels

A sale that already has a return is never restocked twice; the queue says why.

Customer messages & tracking page

Customer notifications

Courier Settings → Customer notifications. Switch on any of the three channels — they use the senders you already set up:

Then tick the statuses worth a message — shipped (booked), picked up, in transit, out for delivery, delivery attempt failed, delivered, returning. Each ticked status has its own text, filled with a sensible default you can edit or Reset to default. Placeholders: {contact_name}, {business_name}, {invoice_number}, {courier}, {tracking_number}, {tracking_url}, {cod_amount} and {cod_note} (“Please keep 1,500.00 ready.” on COD parcels, nothing on prepaid ones).

Messages go to the phone and email on the booking, else the customer's. Each status is sent at most once per parcel, and the timeline records every send — or why one failed — as Notification. A failing channel does not stop the others.

The tracking page

With Show the tracking page on, your online store answers at /track (under the store's address, e.g. https://yourshop.com/online_store/track). Customers enter the tracking number, or their order number with the phone number used on the order, and see the status, a progress bar, the courier and its scan history. The customer's first name, destination city and the courier's delivery details appear only after the order number and phone check — never for a bare tracking number. The page never shows the address or staff notes, and limits how often it can be queried.

{tracking_url} in messages points to this page. If the online store is off, it points to the courier's own tracking page instead.

Courier report & return risk

Couriers → Courier report. For parcels booked in a date range, optionally one courier account:

The same figures follow By courier — to compare couriers on the same lanes — and By city, the 25 busiest destinations, to see where parcels come back.

Return risk

Every customer is rated from their own courier history: parcels returned out of parcels delivered or returned.

BadgeWhen
New customerFewer finished parcels than Rate after this many finished parcels (default 3).
Low return riskBelow half the high threshold.
Medium return riskFrom half the high threshold.
High return riskFrom High risk from (default 30%).

The badge shows in the booking form (with a warning for high risk), next to the customer on Courier Shipments (medium and high only), on the sale's courier panel and on the customer's page; hover it for “2 of 5 finished parcels returned (40%)”. The walk-in customer is never rated. Both thresholds are in Courier Settings → Return risk.

Courier-by-courier setup

What each courier needs and what it does. Push means the courier sends updates to the webhook URL; otherwise status checks keep the shipment current. Each account form has the same fields, with help text, and Test connection lists the codes it can.

Any courier

CourierYou needGood to know
Manual / Other courierNothing; optionally a tracking link.Type the tracking number; update the status by hand. COD and returns work as for any courier.
AfterShipAPI key (Settings → API keys); webhook secret (Settings → Webhooks).Push. Book with any courier, type its tracking number; an optional default courier slug skips detection.
17TRACKSecurity key (API → Settings).Push. 3,000+ carriers; the key also signs the updates.

Pakistan

CourierYou needGood to know
PostExAPI token (merchant portal → Settings).Pickup address code from Test connection. Airway bills, COD settlement. Status checks.
LeopardsAPI key and password (portal → API Settings).Push via the Leopards Push API — give Leopards the webhook URL. Slips, COD payments, test mode.
TCSTCS Connect client ID and secret, Envio username and password, account number.Cost center from Test connection. Labels, COD status, test (UAT) mode. Status checks.
TraxAPI key (portal → Profile).Push — enable webhooks in the Trax portal. Pickup address ID from Test connection; needs an email per order, so set the fallback email.
M&PCOD portal username and password, account number.Pickup location ID from Test connection. COD status. Status checks.
Call CourierLogin ID.Origin branch, shipper city and area IDs. Stocky prints the label. Status checks.
Daewoo FastExAPI key, user and password.Terminal-based COD delivery. Stocky prints the label. Status checks.
BlueExPortal username and password.Tracking only: book in the BlueEx portal, type the CN here.

Shipping aggregators

AggregatorYou needGood to know
EasyPost (USA, global)API key; webhook secret.Push. USPS, UPS, FedEx, DHL and 100+ carriers; a test key buys free test labels.
Shippo (USA, global)API token; optional HMAC secret.Push. shippo_test_… tokens buy free test labels.
Shiprocket (India)An API user (Settings → API → Add New API User), not your main login; webhook security token.Push. Pickup location name from Test connection; optional pickup request; COD remittance.
Sendcloud (Europe)Public and secret key (Settings → Integrations).Push. PostNL, DHL, DPD, GLS, UPS, Colissimo and more.
OTO (Saudi Arabia, GCC)Refresh token (Settings → API Integrations); webhook secret key.Push. Pickup location code from Test connection.
Torod (Saudi Arabia, GCC)Client ID and secret (App credentials).Push. Warehouse code from Test connection.
EasyParcel (Malaysia, SEA)API key (Integration ID).Push. Pays from your EasyParcel wallet; cancel in the EasyParcel portal.
Biteship (Indonesia)API key; the webhook header name and value you set in Biteship.Push. Stocky prints the label.
Shiplogic (South Africa)API key (Integrations → API Keys).Push. Bob Go and The Courier Guy; a white-label portal uses its own API host.
Sendbox (Nigeria)Access token.Push, registered with each parcel. Pays from your wallet; cancel in the Sendbox dashboard.

Gulf & Egypt

CourierYou needGood to know
AramexUsername, password, account number, PIN, entity (e.g. DXB) and country.Domestic and international AWBs with COD. No cancel. Status checks.
SMSA ExpressAPI key.Push once SMSA enables it for you. Cancel, PDF waybills.
J&T Express (KSA, UAE)API account, private key, customer code and password (J&T open platform).Push — set the push address on the open platform. The receiver's state is required.
Naqel Express7-digit client ID and password.Pickup city code (e.g. RUH). Cancel before pickup. Status checks.
Quiqup (UAE)Client ID and secret (from Quiqup); webhook signing token.Push. Same-day, next-day and 4-hour delivery.
Bosta (Egypt, KSA)A Full Access API key, so bookings can be cancelled.Push, registered with each parcel. Booking by district.
Mylerz (Egypt, North Africa, Jordan)Integration username and password.Warehouse name from Test connection. Status checks.

Bangladesh, India & Southeast Asia

CourierYou needGood to know
SteadfastAPI key and secret key; the webhook auth token you set in the panel.Push. Several wrong keys lock API access for an hour. Stocky prints the label.
PathaoClient ID and secret (Developer API); webhook secret.Push. Store ID from Test connection; area is optional; payout invoices.
RedXAPI access token (Developer API → Request token).Push. Booking needs the RedX delivery area.
eCourierUser ID, API key and secret.Package code from Test connection; booking by city and thana. Status checks.
DelhiveryAPI token (Delhivery One → Settings → API Setup).Pickup location = your warehouse name exactly as in Delhivery One. Push (Scan Push) is set up by Delhivery on request.
ShadowfaxAPI token (SFX 360 partner portal).Push — status callbacks via the portal or your account manager.
Ninja Van (SG, MY, TH, ID, VN, PH, MM)Client ID and client key (Settings → IT Settings).Push only — Ninja Van has no status check, so register the webhook URL. Waybills need Ninja Van to enable access.
Flash Express (TH, MY, PH, LA)Merchant ID and secret key (from Flash support).Push. Optional warehouse number and automatic pickup request.
Lalamove (Asia, LatAm, Gulf)API key and secret (Partner Portal → Developers).Push. On-demand vehicles; needs the pickup and drop-off map points; instant quote.

Global express

CourierYou needGood to know
DHL ExpressMyDHL API key and secret (developer.dhl.com, issued with your DHL account), account number.Rates, labels with customs data, optional pickup. No cancel and no push — status checks. In test mode only DHL's sample waybills can be tracked.
FedExAPI key and secret of your Ship/Rate project, account number; the Track project's own key if you created one.Rates, labels, COD, cancel. Push needs FedEx's paid Advanced Integrated Visibility (US/Canada services) and its security token.
UPSClient ID and secret (add Rating, Shipping and Tracking to the app), 6-character account number.Rates, labels (images, 4 × 6), COD, void from US/PR/CA. Optional Track Alert push — UPS bills each tracking number.

International parcels with DHL, FedEx and UPS carry customs data built from the booking: contents, declared value (the COD amount when none is set), quantity and the pickup country as origin. Set Customs value currency on the account if it is not your company currency.

Try it in test mode first. Book a few test parcels before going live: couriers differ in what they accept (phone formats, city names, postal codes), and their error messages appear as is in the booking form.

Status checks run from the scheduler (see Cron & queue) every 15 minutes, at the interval set in Courier Settings — without the cron entry, only couriers that push updates move by themselves. Courier pushes arrive on your site's own address; nothing needs opening on the server.

Customers & ledger

People → Customers. Name, email, phone, address, tax number, an opening balance and a credit limit. The POS creates them on the spot; the store creates them when a shopper registers; the import brings them in bulk.

/next/customers
Customers list
Customers, with their due balance and Pay due on the row.
/next/customers/2/details
Customer details
A customer's page: totals, sales, payments, quotations and returns.

The ledger

/next/customers/2/ledger
Customer ledger
The ledger: everything owed and paid, with a PDF statement.

Every invoice, return and payment for a customer on one statement, with the opening balance, the sales due, the returns due, the payments and the outstanding total. Download PDF produces the statement you send them. Pay due takes a payment against the oldest open invoices. The credit limit — No limit by default — stops the POS and the sale form from going past it.

Two further lists under People split customers by store access: Customers with Login can sign in to the online store; Customers without Login cannot. The Client Portal link under People opens the portal itself; access to it is granted per customer from this list.

Client portal

A separate front door at /portal for business customers — the ones who buy on account, ask for quotations and want their statement without phoning. It is not the online store: no cart, no checkout, no catalogue.

/portal/login
Portal login
The portal sign-in.
/portal/dashboard
Portal dashboard
What a client sees after signing in.

Inviting a customer

People → Customers. Open the row's actions and choose Portal Client. Confirm the email address the invitation goes to and press Enable: an email with a set-password link is sent, and until they use it the customer shows as invitation pending. Disable revokes access without deleting anything.

/portal/invoices
Portal invoices
Invoices with PDF download.
/portal/statement
Portal statement
The statement.
Portal pageWhat the client can do
DashboardOutstanding balance, recent invoices and payments.
InvoicesEvery sale, with status, paid and due, and a PDF of each.
Payments, StatementPayments received and the running statement.
QuotationsRead the quotations you sent, and request a new one.
AppointmentsBook an appointment (with the bookings module).
ContractsRead their contracts and download attachments (with the contracts module).
Knowledge baseThe articles you publish (with the knowledge-base module).
ProfileChange the password, switch language, or delete the account.
Portal on a phone
The portal on a phone; it installs as a PWA.

Loyalty & promotions

Loyalty points

Settings → Loyalty Rewards. Customers earn points on what they spend at the rate you set (points per amount, a minimum sale, an expiry). Points show on the customer's page, on the POS when the customer is picked, and in the store account. They are spent two ways: converted into a discount at the point-to-amount rate, or redeemed for a reward from the catalogue on this page — a discount amount, a gift card or a product, each with a points cost, a stock and a per-customer limit. Redemptions are listed with their status and fulfilled from here; points can be credited or deducted by hand with a note.

/next/loyalty/rewards
Loyalty rewards
The rewards catalogue and redemptions.

Promotions

Promotions. Rules that apply themselves at the POS checkout: a percentage or a fixed amount off, on chosen products, categories or the whole cart, within a date range, optionally behind a promo code, with a usage limit. The register lists the promotions that matched; the Promotion Usage report shows what each one cost.

/next/promotions
Promotions
Promotions with their type, period and usage.

The online store has its own coupons and flash sales; they are separate from POS promotions on purpose, because a web coupon and a counter promotion rarely have the same rules.

E-wallet & commissions

E-wallet

E-Wallet. A prepaid balance per customer. Top it up in the admin or let shoppers do it in the store; spend it as a payment method at the POS and at checkout; refund to it instead of to cash. Wallet Items are the products or amounts on offer; the dashboard shows balances, top-ups and spend; the settings decide minimums and whether withdrawals are allowed.

/next/ewallet/dashboard
E-wallet dashboard
The e-wallet dashboard.

Commissions

Commissions. For salespeople paid on what they sell. A program sets the rule — a percentage of the sale, of the profit, or a fixed amount per line — and which products it covers; agents are the users or employees in it; rules add tiers and exceptions. Every sale with a sales agent accrues, receipts record what was paid out, and the report reconciles the two.

/next/commissions/programs
Commission programs
Commission programs.

Setting up the store

The online store sells the products you mark visible, from the warehouses you choose, with the same prices, stock and customers as the counter. It is switched on per install under Settings → Modules → Store, then configured from Store → Settings.

/next/store/settings
Store settings
Store settings: one tab per concern, and one per theme with the blocks that theme draws.
  1. Basics

    Store name, the theme, the warehouses it sells from (or all), the default language and the display currency. Online store enabled is the master switch; off, the storefront answers with a closed page.

  2. Address

    By default the store lives at /online_store. Set a custom URL path such as /shop, or tick use the root domain so the shop is your home page and the admin stays at /login and /next. On the root domain the shop's sign-in and register pages move under /customer/…. Old links are redirected.

  3. Stock behaviour

    Show stock or not, hide out-of-stock products, allow or prevent overselling, hide prices for guests (a wholesale catalogue that shows prices only after sign-in).

  4. Registration

    Public registration on or off; require an invite code, admin approval, email verification, or any combination. See Customer accounts.

  5. Returns and reviews

    The return window in days, whether shoppers may cancel unshipped orders, and whether reviews publish at once or wait for moderation.

  6. Make products visible

    A product appears in the store only when its online store switch is on. Set it per product, or in bulk from the product list.

Real estate

With the Real Estate theme the store becomes a listings site: Store → Real Estate holds properties (for sale or rent, price, beds, baths, area, photos, map), their categories and the inquiries the form sends. Products and the cart are not used.

Themes

Five themes on one catalogue. Switching is a dropdown in Store → Settings → Basics; each theme has a tab of its own for the blocks it draws, and every theme shares the same product page, cart, checkout and account.

/online_store · Default
Default theme home page
Default — collections and homepage blocks you arrange yourself.
/online_store · Electronics
Electronics theme home page
Electronics — hero slider, promo banners, category tiles, top picks / best rated / on sale tabs, brand row, testimonials.
/online_store · Toys & Baby
Toys theme home page
Toys & Baby — playful palette, four promo tiles, a welcome coupon bar.
/online_store · Grocery
Grocery theme home page
Grocery — delivery-time badge, weekly deals with a countdown, category circles, popular-now row, aisles.
/online_store · Real Estate
Real estate theme home page
Real Estate — listings with sale/rent, price, beds, baths, area, a map and an inquiry form.

Each theme tab holds its own slides, tiles, banners, section headings, featured products per tab, deals and testimonials. What you fill in for Electronics is kept when you try Grocery, so switching back loses nothing. The demo seeders described under Demo catalogues fill each theme with a matching catalogue.

/online_store/shop
Shop page with filters
The shop page: search with suggestions, filters by category, collection and price, sort.
/online_store/product/…
Product page
The product page: gallery, variants, reviews, questions and answers, related products, wishlist, compare, size guide.
Grocery theme on a phone
Grocery on a phone.
Toys product page on a phone
A product page on a phone.
Property page on a phone
A property listing on a phone.

Collections, banners, pages & menus

Everything a shopper sees that is not a product is managed under Store.

PageWhat it is for
CollectionsNamed groups of products — New arrivals, Gifts under 20, Summer — with an image and a slug. The Default theme's home page is built from them; every theme offers them as a filter.
BannersImages with a title, a link and a position for the hero and promo slots.
PagesStatic content — about, delivery, terms, privacy — with a rich-text editor and a slug at /pages/….
MenusThe header and footer navigation: links to pages, collections, categories or any URL, in the order you drag them.
Popup messagesA one-time announcement or newsletter prompt, with a schedule.
Product reviewsRatings and text left by verified buyers; approve, reply or hide. Auto-approval is a store setting.
Subscribers, MessagesNewsletter sign-ups from the footer form, and what the contact page sends.
/next/store/collections
Collections
Collections.
/next/store/banners
Banners
Banners.
/next/store/pages
Pages
Pages.
/next/store/menus
Menus
Menus.

Shipping, tax & payment

Checkout quotes are computed on the server from these three lists, so the shopper's total is the same one that lands on the sale.

/next/store/shipping-methods
Shipping methods
Shipping methods.
/next/store/tax-rates
Tax rates
Tax rates.
/next/store/coupons
Coupons
Coupons.
/online_store/flash-sales
Flash sales page
Flash sales with a countdown.

Payment gateways

/next/store/payment-gateway
Store payment gateways
Store payment gateways, each with its keys and a sandbox switch.
KindMethodsNotes
OfflineCash on delivery, cash on pickup, bank transfer, mobile money, GCashNo keys. Bank transfer lets the shopper upload a proof of payment; you confirm the order when the money arrives.
Card & walletStripe, PayPal, Paystack, Flutterwave, RazorpayPublic and secret keys, an optional webhook secret, and a sandbox switch for testing. The order is marked paid when the gateway confirms.
RegionalbKash, SSLCommerzBangladesh. App key, secret, username and password (bKash); store ID and password (SSLCommerz).
/online_store/checkout
Checkout
Checkout: address, shipping method, payment method, coupon and a running summary.

Orders & requests

Store → Online Orders. A web order is a sale with a source of online: it appears here and in Sales, moves stock from the store's warehouse, and can be shipped, returned and refunded like any other. Confirm it, set the shipping status, print the invoice; with the kitchen on, confirmed orders can become tickets.

/next/store/orders
Online orders
Online orders with payment and shipping status.
PageWhat arrives there
Returns requestsA shopper's request to return or cancel, from their account, within the return window. Approve to create a sale return; refuse with a reason.
Quote requestsA shopper's request for a price on a service or quote-only product. Answer with a quotation.
MessagesThe contact form.
Product reviewsRatings awaiting moderation.
Pending customersRegistrations awaiting your approval, when approval is required.
/next/store/returns
Return requests
Return requests from the store.

Customer accounts

A shopper can check out as a guest or with an account. The account is the same customer row the POS and the ledger use — sign in at the counter with the same email and the loyalty points are there.

/online_store/account
Store account page
My account: orders, returns, wallet, rewards, wishlist, addresses, questions, preferences.
/online_store/account/orders
Store account orders
Orders with invoice PDF, tracking and the return button.

Who may register

Store → Settings → Basics → Registration access control. Four switches that combine:

Sign-in, registration, password reset and verification pages live under the store's address (/online_store/login, or /customer/login on the root domain).

Branding, SEO & PWA

Store → Settings → Branding, Contact, SEO, Social. Logo and tagline, favicon, primary and secondary colours, font family, whether shoppers get a dark-mode toggle, the top bar and footer text, contact details, social links, and the cookie-consent banner.

SEO: a title template ({product} — {store}), a default description, per-product and per-page SEO fields, an automatic sitemap.xml and robots.txt. Languages and currency: the store switcher offers the languages enabled in Settings and shows prices in the display currencies you enable; orders are still recorded in the base currency unless multi-currency is on.

PWA: Settings → PWA holds the name, icons and colours for each installable surface — the admin, the store, the customer display and the portal. On HTTPS the store shows an install prompt and works as an app on a phone's home screen.

/next/settings/pwa
PWA settings
PWA settings: one manifest per surface.

Accounts, deposits & expenses

The simple books most shops start with, under Accounting. They work with or without the double-entry ledger described in the next section.

/next/accounts
Accounts
Accounts and their balances.
/next/expenses
Expenses
Expenses by category, with attachments.
PageWhat it records
List accountsThe till, the bank, the mobile-money float — each with a number, an opening balance and a running balance moved by every payment, deposit, expense and transfer that names it.
DepositsMoney in that is not a sale: an owner's injection, a refund from a supplier, interest. Categorised under Deposit Category.
ExpensesMoney out that is not a purchase: rent, wages, electricity, fuel. A category, an account, a date, an amount, a note and a receipt attachment. The Expense Report totals them by category and period.
Transfer moneyMoves a balance between two accounts — banking the till, funding the float.
/next/expenses/create
Create expense
Recording an expense.
/next/deposits
Deposits
Deposits.

The Cash Flow report reads all four together with sales and purchase payments to show what came in and went out of each account over a period.

Accounting

Accounting → Dashboard, Chart of Accounts, Journal Entries and the financial reports. Proper double-entry books that post themselves: with the auto journal entries switch on (Feature switches), every sale, purchase, return, payment, expense, deposit and money transfer writes a balanced journal against the chart of accounts. Nothing has to be keyed twice.

/next/accounting-v2/dashboard
Accounting dashboard
The accounting dashboard: revenue, expenses, receivables, payables and the recent journals.

Chart of accounts

/next/accounting-v2/chart-of-accounts
Chart of accounts
Assets, liabilities, equity, income and expenses, numbered and nested.

A standard chart is created for you — cash and bank, receivables, inventory, payables, sales, cost of goods sold, expense accounts, tax accounts. Rename, renumber or add accounts to match your accountant's chart; the automatic journals map onto the accounts you mark for each purpose.

Journal entries

/next/accounting-v2/journal-entries
Journal entries
Journals: automatic ones reference the document they came from; manual ones can be drafted and posted.

Automatic journals are posted as the document is saved and carry its reference. Manual journals — an accrual, a depreciation charge, an owner's drawing — are entered as draft, must balance, and are posted when you are sure. Posted journals are not edited; reverse them with a new entry.

The statements

/next/accounting-v2/reports/trial-balance
Trial balance
Trial balance.
/next/accounting-v2/reports/profit-and-loss
Profit and loss
Profit and loss.
/next/accounting-v2/reports/balance-sheet
Balance sheet
Balance sheet.
/next/accounting-v2/reports/tax-report
Tax summary
Tax summary: tax collected on sales against tax paid on purchases.

Trial balance, profit and loss, balance sheet and tax summary, each for any period, each exportable to Excel and PDF. If you began trading before turning the switch on, the journals for existing documents are not created retroactively — post an opening-balance journal as of the start date instead. QuickBooks and Xero can take the invoices and payments if your accountant works there.

Multi-currency

Off by default. Turn it on under Feature switches, then give each currency in Settings → Currencies an exchange rate against the base currency. From then on a sale, a purchase or an online order can be recorded in another currency: the document keeps its own currency, rate and totals, and the base-currency equivalent is shown alongside and used everywhere else.

Rates are manual — you type them and update them; nothing is fetched. Reports, stock valuation, the ledger and the accounting journals stay in the base currency, so a euro sale and a dollar sale add up in one figure. The store's currency switcher is a separate, display-only feature that works even with this switch off.

ZATCA e-invoicing

For businesses in Saudi Arabia. Settings → ZATCA E-Invoicing.

/next/settings/zatca
ZATCA settings
ZATCA: phase 1 QR, phase 2 onboarding, and the documents submitted.

Changing the environment resets the credentials and requires onboarding again. Test in the sandbox with a test OTP before touching production.

Company structure

The HRM module (Settings → Modules → HRM) starts with the shape of the organisation, under HRM:

/next/hrm/departments
Departments
Departments, with their head and company.
ListNotes
CompaniesOne or more legal entities; employees belong to one.
Departments, DesignationsThe org tree and the job titles.
Office shiftsWorking hours per weekday. Attendance is measured against the employee's shift.
HolidaysPublic holidays per company; attendance and leave skip them.
Leave typesAnnual, sick, unpaid and so on, with the days allowed per year.

Employees, attendance & leave

/next/hrm/employees
Employees
Employees.
/next/hrm/attendance
Attendance
Attendance: clock-in, clock-out, late and hours per day.

Employees carry personal details, the company, department, designation and shift, the joining date, documents with expiry, and the basic salary the payroll starts from. An employee may or may not be a system user — a warehouse picker without a login is still on the payroll.

Attendance is a row per employee per day: clock in, clock out, the hours and whether they were late against the shift. Enter it by hand, import it, or let staff record it. The Attendance Summary report totals days, hours and lateness per employee for a month.

/next/hrm/leaves
Leave requests
Leave requests and their status.

Leave requests name a type, a period and a reason, and wait for approval. Approved leave counts against the type's allowance and shows on the attendance grid.

Payroll

/next/hrm/payrolls
Payroll
Payroll runs per month with the net pay and the payment status.

HRM → Payroll. A payroll entry is a payment to an employee: the employee, the date, the amount (pre-filled from the basic salary on their record), the account it is paid from, the payment method, a reference and a status. The list is the record of what was paid to whom and when, filterable by month and exportable. Stocky does not compute income tax or social contributions for you, because those differ by country and year — enter the net amount you actually pay.

Because a payroll names an account, it moves that account's balance and reaches the cash-flow report; with auto journals on it is posted to the ledger as well.

Recruitment & meetings

Two small modules of their own, each with a switch under Settings → Modules.

/next/recruit/dashboard
Recruitment dashboard
Recruitment: jobs, candidates, applications and interviews.
/next/meeting/dashboard
Meetings dashboard
Meetings with a calendar and reminders.

Recruits and Jobs: job openings by category, candidates, their applications with a status, interviews with a date and an interviewer, and a report of the funnel. Meetings: a meeting with attendees, an agenda and a time, on a calendar, with reminders sent by the scheduler (see Cron & queue) and a report of attendance.

Projects & tasks

Projects Management. Projects with a client, a budget, dates and members; tasks with an assignee, a priority, a due date and a status, in a list or on a drag-and-drop board; milestones; timesheets of hours per task; and reports of hours and progress per project.

/next/projects/dashboard
Projects dashboard
The projects dashboard.
/next/tasks/board
Task board
The task board.

Bookings

Booking Management. Appointments and reservations: a customer, a service or a resource, a date and time, a status and a note, in a list and on a calendar. Trays hold the items prepared for a booking — a hamper, a cake, a hire kit — so the shop knows what to have ready. With the Google Calendar connection in System Settings, bookings appear in a Google calendar too; portal clients can book their own appointments.

/next/bookings
Bookings list
Bookings.
/next/bookings/calendar
Booking calendar
The calendar view.

Service & maintenance

Service & Maintenance. For repair shops, phone and computer clinics, appliance servicing, workshops. A service job is a device or an item brought in by a customer, and it moves through a fixed path:

intake → diagnostic → quoted → in progress → ready → delivered

/next/service/jobs
Service jobs
Service jobs with their status; the sidebar filters Awaiting approval, Ready for pickup and Awaiting payment.
/next/service/jobs/details/2
Service job details
A job: the item, the fault, the technician, the checklist, photos, parts and labour, payments and the printable job card.
/next/service/technicians
Technicians
Technicians.
/next/service/checklists
Checklist items
Checklist items.

Subscriptions

Subscription Product. Recurring sales of a product or service: a customer, the product, a billing cycle (weekly, monthly, yearly), a start date and the next billing date. Each cycle produces a sale; the list shows what is due next and what has lapsed. For water deliveries, maintenance contracts, memberships and software seats.

/next/subscriptions
Subscriptions
Subscriptions with cycle and next billing date.

Manufacturing

Manufacturing (MRP). For businesses that make what they sell. A bill of materials lists the components and quantities that make one unit of a finished product; a production order asks for a quantity of it, reserves the components, and on completion consumes them from stock and adds the finished goods. Work centres are the machines or stations; the shop floor page is the work orders in progress; quality control records inspections and rejects; planning compares demand with stock and open orders to say what to make and buy; the reports cover output, cost and yield.

/next/mrp
Manufacturing dashboard
The manufacturing dashboard.

Assets & fleet

/next/assets/dashboard
Asset dashboard
Assets: what the business owns and who has it.
/next/fleet/dashboard
Fleet dashboard
Fleet: vehicles, fuel and maintenance.

Asset Management: the things the business owns and does not sell — laptops, tills, tools, furniture — by category, with a purchase date and value, assignments to employees, transfers between locations, maintenance, depreciation schedules, and a Due Assets list of what needs returning or checking. A daily scheduled task flags assets whose validation is due.

Fleet Management: vehicles with registration and documents, fuel logs with cost per litre and consumption, maintenance with reminders, assignments to drivers, and reports of cost per vehicle.

Documents, contracts & knowledge base

/next/documents
Document archive
The document archive.
/next/contracts
Contracts
Contracts.
/next/kb
Knowledge base
The knowledge base.

Marketing

Marketing. Campaigns by email, SMS or WhatsApp to a customer segment — everyone, top spenders, inactive for 90 days, a loyalty tier — using a template with placeholders, sent now or scheduled. The dashboard and the reports show sends, deliveries and the sales attributed to a campaign. Templates for each channel and the gateway defaults live under Marketing Settings.

/next/marketing/dashboard
Marketing dashboard
The marketing dashboard.
/next/marketing/campaigns
Campaigns
Campaigns.

Scheduled campaigns are sent by the scheduler every minute — they need the cron entry from Cron & queue. Sending thousands of emails from a shared host is how a domain gets blacklisted; for large lists connect Mailchimp and let it do the sending.

Hospital & school

Two vertical modules for businesses that also run a clinic or a school alongside the shop — a pharmacy with a consulting room, an academy with a bookshop. Both are switched on under Settings → Modules and use the same customers, users and accounting.

/next/hospital/dashboard
Hospital dashboard
Hospital: patients, appointments, consultations, admissions, lab and billing.
/next/school/dashboard
School dashboard
School: students, enrolment, attendance, timetable, exams and fees.

Hospital Management: patients, doctors and departments, appointments, consultations, admissions with wards and beds, a lab test catalogue with orders, billing and reports. School Management: students, teachers, academic setup (classes, sections, subjects), enrolment, attendance, a timetable, exams and results, fees and reports.

Integrations: before you start

Integrations → All Integrations lists every connector with its state — connected, configured, or not set up — and opens each one's own page. Most pages carry a Guide tab that repeats the steps below with this server's own addresses and cron lines filled in, ready to copy.

/next/integrations
Integrations hub
The integrations hub.
GroupConnectorsWhere
Online shops & marketplacesWooCommerce, Shopify, Salla, PrestaShop, JumiaEcommerce Platforms in the sidebar
Accounting & dataQuickBooks Online, Xero, Google SheetsIntegrations
Messaging & marketingTelegram, Slack, WhatsApp Business, MailchimpIntegrations
DevelopersWebhooks, REST APIIntegrations → Webhooks
ElsewhereGoogle Calendar, Stripe and the payment gatewaysSettings

Switch it on, give people access

An integration you cannot find in the sidebar is switched off or not permitted:

Three ways data moves

What it isNeedsUsed by
Right awaySent straight after the sale or product is saved, in the same request, after the screen has already been answered — the cashier never waits.NothingWooCommerce and Shopify instant stock push, WooCommerce push-on-save, Telegram
Incoming webhooksThe other platform calls Stocky the moment something happens there.A public https:// address — not localhost, not .testShopify, Salla, WhatsApp (delivery receipts and replies), payment gateways
Background & scheduledQueued work and timed syncs.A cron entryEverything else — see the table below

Cron lines at a glance

Add only the lines for the integrations you use. Replace /path/to/stocky with the install folder — each integration's Guide tab shows its lines with the real path already filled in. On cPanel these go in Cron Jobs; use the full path to PHP 8.2+ if php is older. On Windows, create a Task Scheduler task with program php, the same arguments, started in the install folder.

ForCron lineWhat it does
WooCommerce0 * * * * cd /path/to/stocky && php artisan woocommerce:sync --scope=stockStock to the shop, hourly
*/15 * * * * cd /path/to/stocky && php artisan woocommerce:sync --scope=ordersNew and changed orders in, every 15 minutes
0 2 * * * cd /path/to/stocky && php artisan woocommerce:sync --scope=products --only-unsyncedPublish products not yet in the shop, nightly
0 3 * * * cd /path/to/stocky && php artisan woocommerce:sync --scope=pull-productsProduct changes made in the shop, nightly
30 3 * * * cd /path/to/stocky && php artisan woocommerce:sync --scope=customersCustomers in, nightly
Shopify*/5 * * * * cd /path/to/stocky && php artisan shopify:syncRuns whichever steps of each shop's plan are due
* * * * * cd /path/to/stocky && php artisan queue:work database --queue=shopify --stop-when-empty --max-time=55 --timeout=600Works the syncs started from the Sync Centre in the background, a slice at a time. Without it they still finish, but only while the Sync Centre page stays open
Telegram* * * * * cd /path/to/stocky && php artisan telegram:sendRetries failed messages and sends events raised in the background
Salla & Xero0 0 * * * cd /path/to/stocky && php artisan integrations:keep-aliveDaily ping that stops the connection expiring
Google Sheets30 2 * * * cd /path/to/stocky && php artisan google-sheets:auto-exportNightly export, when auto-export is on
Couriers*/15 * * * * cd /path/to/stocky && php artisan couriers:syncStatus checks for couriers that cannot push updates, and COD payout checks
Background queue* * * * * cd /path/to/stocky && php artisan queue:work database --queue=webhooks,default --stop-when-empty --max-time=55Outgoing webhooks, Slack, WhatsApp automations, Xero and QuickBooks auto-sync, Mailchimp auto-sync, Google Calendar

Append >> /dev/null 2>&1 to each line to keep cron from emailing its output.

Pick one style, not both. The single schedule:run line from Cron & queue already runs every job above on the same timetable. Use either that one line, or the per-integration lines here — with both, every sync runs twice.

WooCommerce

Ecommerce Platforms → WooCommerce. Two-way sync between Stocky and a WordPress shop: products, stock, categories, brands, customers and orders. Stocky is the source of truth for stock and catalogue; WooCommerce is where online orders are placed.

/next/woocommerce
WooCommerce integration
The WooCommerce hub: status, settings, and a tab per entity with its sync buttons and logs.

Connect the shop

  1. Create REST API keys in WooCommerce

    In WordPress: WooCommerce → Settings → Advanced → REST API → Add key, permission Read/Write. Copy the consumer key (ck_…) and consumer secret (cs_…) — the secret is shown only once.

  2. Optional: a WordPress application password

    Only needed for product images: the WooCommerce API moves everything else, while the WordPress API searches the Media Library and uploads images that are not there yet. Use a WordPress user who can manage media and create the password under Users → Profile → Application Passwords. Leave both fields empty and everything still syncs except images.

  3. Enter them in Stocky

    On the Settings tab: the store URL — the site address with https:// and no trailing slash, e.g. https://yoursite.com — the consumer key and secret, and optionally the WordPress username and application password. Save runs a connection test against the shop; the status tile turns Connected.

The first sync

Each tab — Products, Stock, Categories, Brands, Customers, Orders — shows what is linked and what is not, and offers a push (Stocky → WooCommerce) or a pull (WooCommerce → Stocky). On a fresh connection, go in this order:

  1. Categories, then brands

    So a pushed product lands in the right category.

  2. Products

    Push to publish your catalogue, or pull if the shop already has it. If both sides already have the same products, use Auto-link by SKU on the Products tab first, so nothing is created twice.

  3. Stock

    Push. From then on keep it right with the instant push and the hourly sync below.

  4. Customers and orders

    Pull. Orders become sales in Stocky.

EntityStocky → WooCommerceWooCommerce → StockyMatched on
Products & variantsYes — details, price, variants, imagesYesThe saved link, then SKU = product code
StockYes — total across all warehousesThrough a product pullLinked products only
Categories, brandsYesYesThe saved link, then name
CustomersYes (needs an email)YesEmail or phone
Orders—Yes, as salesOrder lines by SKU

Imported orders and pulled products use the default warehouse from System Settings; stock published to WooCommerce is the total across every warehouse, with negative figures sent as zero.

Right away: push stock and products as they change

Off until you ask for it — and the setting people miss. Without it a POS sale does not reach WooCommerce when it happens: the shop finds out at the next hourly stock sync, and until then it can sell a unit you have already sold at the till.

Neither needs a queue worker or a cron entry: the push runs after the screen has been answered, pushes never overlap, and if the shop stops answering they pause for five minutes (recorded in Logs) and catch up with the next push. Bulk operations such as deleting a product move stock without firing an event — keep the hourly stock sync on as the safety net.

On a schedule

WooCommerce has no webhook receiver here, so everything coming in — orders, product changes made in the shop, customers — arrives on the schedule. The five WooCommerce cron lines cover it; each runs on its own, so add only what you want. woocommerce:sync works through its own queue while it runs, so no separate worker is needed. Without any cron, every tab still syncs on demand while its page is open — orders then arrive only when someone presses the button.

CommandDoes
php artisan woocommerce:sync --scope=stockPush stock for every linked product now
php artisan woocommerce:sync --scope=products --only-unsyncedPublish products that have no WooCommerce link yet
php artisan woocommerce:sync --scope=ordersImport orders changed since the last clean run
php artisan woocommerce:sync --scope=orders --fullRescan every order instead of only recent changes
php artisan woocommerce:sync --scope=pullEverything inbound: products, orders, customers

--user= chooses which user imported sales are recorded under. The orders pull only moves its bookmark forward after a run with no errors, so an order that failed — usually because one of its products is not linked — is retried on the next run.

Sync tuning & logs

The Settings tab has a Sync tuning card for slow or busy hosts: products per batch (default 25), stock products per batch (25), the HTTP timeout (30 s), retries on timeouts and 429/5xx answers (2), how long a run may sit before it counts as stuck (10 min), and media timeouts for image uploads. A blank field restores the default. The Logs tab keeps every run with its outcome, filterable by action, status and date.

Troubleshooting

SymptomCause and fix
Every call fails with 401The store URL starts with http://. WooCommerce only accepts key authentication over HTTPS — use the https:// address.
Products duplicated in the shopSKUs differ between the two sides. Make the WooCommerce SKU equal the Stocky product code, then Auto-link by SKU.
An order never importsOne of its lines is a product with no link. Check the Unmapped report on the Products tab; the order is retried on the next run.
Everything shows as unsynced after editing settingsChanging the store URL, consumer key or consumer secret clears every link — products, categories, brands and customers sync again as if to a new shop. Intended when you really switch shops.
Images missingNo WordPress application password, or the user cannot manage media.
Shop stock lags behind the tillPush stock the moment it changes is off.

Shopify

Ecommerce Platforms → Shopify: Dashboard, Stores (one or more shops), Sync Centre (manual runs), Mappings (pairs Stocky records with Shopify ones), Logs and Guide. Products, inventory, customers, collections and fulfilments move both ways; orders come in from Shopify.

/next/shopify
Shopify dashboard
The Shopify dashboard.

Create the app in Shopify

Since January 2026 Shopify no longer creates custom apps inside the shop admin. Use whichever applies:

Dev Dashboard app (new shops)Legacy custom app (made before 2026)
Wheredev.shopify.com → Apps → Create app. Grant the scopes below, then install the app on the shop. The app and the shop must belong to the same Shopify organisation.Shop admin → Apps → Develop apps → your app → API credentials
CopyClient ID and Client secret from the app's Settings pageThe Admin API access token (shpat_…) and the API secret key
Webhook signing secretThe client secret — nothing extraThe API secret key — not the access token
Token renewalAutomatic: Stocky exchanges the ID and secret for a token and renews it before its 24-hour expiryThe token does not expire
To syncGrant these Admin API scopes
Products, collectionsread_products, write_products
Inventoryread_inventory, write_inventory, read_locations
Customersread_customers, write_customers
Ordersread_orders — plus read_all_orders for orders older than 60 days
Fulfilmentsread_merchant_managed_fulfillment_orders, write_merchant_managed_fulfillment_orders, read_assigned_fulfillment_orders, write_assigned_fulfillment_orders

Connect a store

Stores → Add store. Every setting is changed the same way later — the pencil on the row, or Edit store on the store's page.

  1. Connection

    A name, the shop domain (acme.myshopify.com; pasting the admin URL works too), the credential type and its values, the API version (default 2024-10) and, for a legacy app, the webhook signing secret. Saving tests the connection and fills in the shop's name and currency. When editing, a blank credential field keeps the stored value.

  2. Where data lands

    The Stocky warehouse and the Shopify location it maps to (Fetch locations from Shopify fills the list) — each store pairs one warehouse with one location, and inventory sync and order import refuse to run without them. Also: which price is sent (retail, wholesale or minimum), and whether to create missing products (no SKU match) and missing customers (no email match). With the latter off, an order from an unknown customer is skipped.

  3. What to sync

    A switch per entity. Off here means off everywhere — manual, scheduled and webhooks.

Products are matched on SKU (the product or variant code), never on title: before creating a product in Shopify, Stocky looks for a listing with the same SKU and links it instead. Customers match on email; customers without one are skipped. Mappings lets you link anything by hand; unlinking only forgets the pair and deletes nothing.

Automatic sync

Two mechanisms keep a shop in step, and they cover different things — use both.

WebhooksScheduled sync
DirectionShopify → StockyBoth ways
SpeedSecondsThe step's interval (5 minutes to 7 days)
CoversNew orders, order changes, cancellations and fulfilments; product, customer and stock edits made in ShopifyStock and catalogue pushed out, and anything a missed webhook dropped
NeedsA public HTTPS address and the signing secretThe shopify:sync cron line
  1. Subscribe to the webhooks

    On the store's page, Webhooks tab, press Register in Shopify. It subscribes the shop to every topic whose entity is switched on — orders/create, orders/updated, orders/cancelled, orders/fulfilled, products/create, products/update, customers/create, customers/update, inventory_levels/update — pointing at https://your-domain/api/shopify/webhook. Pressing it twice is safe; Tidy up removes stale subscriptions. Each delivery is recorded once, so Shopify's retries cannot create a second order, and one that failed can be Replayed from the same tab.

  2. Choose what runs on a schedule

    Edit the store, Automatic sync tab: switch it on, set a default interval (60 minutes unless changed) and build the plan. A step is one entity in one direction with its own interval — Orders · Shopify → Stocky every 15 min, Inventory · Stocky → Shopify every 30 min. Leave the plan empty and the store pulls orders and pushes stock at the default interval, which suits most shops. Add the shopify:sync cron line; five minutes is the finest interval it can honour.

  3. Selling the same stock at a counter? Push stock the instant it changes

    Off until you ask for it. On the same tab, Push stock the moment it changes makes any stock movement in the store's own warehouse — POS sale, return, adjustment, received purchase — push just those products within seconds. It needs Inventory switched on, the store connected, and a warehouse and location set; only mapped products are pushed. Nothing else to install: the push runs after the sale has been answered. Keep the scheduled inventory push as the safety net for bulk operations.

  4. Watch it

    The store's Overview shows every step with its last run, next due time and state — Waiting, Due now, Running, or Blocked with the reason (usually no warehouse or no location). Runs and Errors keep the history; scheduled runs appear exactly like manual ones.

  5. Large syncs run in the background

    A sync started from the Sync Centre answers at once and is worked by the Shopify queue cron line in short slices, each carrying on from where the last stopped — so hosting that ends long web requests (LiteSpeed, nginx, a load balancer) cannot cut a big catalogue off part-way, and closing the page does not stop it. Without that cron line the open Sync Centre page carries the run on itself after a few seconds, one short request at a time.

A step is due when it last started longer ago than its interval, so a sync you start by hand postpones the next automatic one. Do the first catalogue push by hand — after a --dry-run — before putting it on a schedule.

CommandDoes
php artisan shopify:sync --listShow what is due for each store, and why a step is blocked
php artisan shopify:sync --store=acme.myshopify.com --entity=products --dry-runWalk a products push and report, writing nothing
php artisan shopify:sync --store=1 --entity=orders --since=2026-01-01 --forcePull orders from a date now, ignoring the interval
php artisan shopify:sync --entity=customers --only-unsyncedPush only customers not yet linked

Troubleshooting

SymptomCause and fix
Test connection: 401The token or client secret was rejected — copy it again from the app.
Test connection: 403A scope is missing. Add it in the app, reinstall it on the shop.
Test connection: 404Wrong shop domain, or an API version Shopify no longer serves.
Webhooks registered but every delivery refusedNo signing secret on the store, or (legacy app) the access token was pasted where the API secret key belongs.
No webhooks arrive at allThe site is not on public HTTPS — Shopify does not deliver to localhost or .test.
A step stays BlockedNo warehouse or no Shopify location on the store.
Mappings goneThe shop domain was changed, or the store deleted and re-added — both clear its links.
An image removed in Stocky is still in ShopifyIntended: removals are not mirrored. Images are re-sent only when they change.

Salla

Ecommerce Platforms → Salla. Products, stock and orders with a Salla store (Saudi Arabia and the Gulf). Orders arrive the moment they are placed, through Salla's webhooks.

/next/integrations/salla
Salla integration
Salla: connection, sync scopes and the log.
  1. Create the app in Salla Partners

    On salla.partners, create a private app in Custom Mode. Copy its Client ID and Client Secret into the Salla page in Stocky and save.

  2. Set the addresses the page shows

    In the app, set the OAuth callback to https://your-domain/salla/callback. Under Webhooks, choose the Signature strategy, copy its secret into Stocky's Webhook Secret field, set the webhook URL to https://your-domain/api/salla/webhook, and subscribe at least to order.created, order.updated, product.updated, product.deleted, app.store.authorize and app.uninstalled.

  3. Connect

    Choose the stock warehouse (or all warehouses added together), press Connect with Salla, sign in and approve. Test Connection shows the store name.

WhatDirectionNotes
ProductsPush and pullPush creates or updates simple products (name, price, quantity, SKU = product code); variant products are not pushed. Pull brings variants too and matches on the link, then SKU — new products arrive with zero stock.
StockPushLinked items only. A variant needs one product pull first so its Salla id is known.
OrdersIn, automaticallyThrough webhooks, as sales with reference SLA-…; Pull orders backfills. Status and payment of an already-imported order are updated as they change. Customers match on email, then phone.

Salla access tokens last 14 days and the refresh token one month — and each refresh token works once. Stocky renews them on its own; the keep-alive cron line makes sure a quiet store is still renewed before the month runs out. If it lapses, press Connect again. Order lines are matched on SKU; lines that match nothing are listed in the sale's notes, and an order with no matching line is skipped with a warning in Logs.

PrestaShop

Ecommerce Platforms → PrestaShop. Products, stock and orders with a PrestaShop store, over its Webservice. There are no webhooks: orders come in when you pull them.

  1. Create a Webservice key

    In the PrestaShop back office: Advanced Parameters → Webservice, enable the webservice, and add a key with View, Add, Edit on products and stock_availables, and View on orders and customers.

  2. Connect

    Enter the store URL, the key, the shop language ID (1 unless your default language differs — it is the language product names are written in) and the stock warehouse. Test Connection reads one product.

Keep references identical on both sides. A stock push that fails with “No stock_available row for product N” means that product has no stock record in PrestaShop yet — save it once there.

Jumia

Ecommerce Platforms → Jumia. Pushes prices and stock to your Jumia listings and imports Jumia orders.

  1. Generate an API key

    In Jumia Seller Center: Settings → Integration Management, generate an API key.

  2. Connect

    Enter the API URL for your country — e.g. https://sellercenter-api.jumia.com.ng (Nigeria), .co.ke (Kenya), .com.eg (Egypt) — the Seller Center account email, the API key and the stock warehouse. Test Connection reads one order.

New listings are created in Seller Center, not from Stocky; the Seller SKU must equal the Stocky product code. Nothing runs on a schedule — push and pull from the page.

QuickBooks Online

Integrations → QuickBooks Sync. Sends customers and sales to QuickBooks Online as customers and invoices, so your accountant works from the same figures.

/next/settings/quickbooks
QuickBooks sync
QuickBooks Sync.
  1. Create an app at Intuit

    On developer.intuit.com, create an app with the Accounting scope (com.intuit.quickbooks.accounting). Under its keys, add the redirect URI https://your-domain/quickbooks/callback — it must match character for character, over HTTPS.

  2. Enter the keys

    On the Settings tab: Client ID, Client Secret, the same redirect URI, the environment (Development for sandbox keys, Production for live ones), and optionally the income account name invoices should post to.

  3. Connect

    On the Connection tab press Connect, sign in to Intuit and choose the company.

The Audit Log tab records every call; a sale that failed to sync keeps the error on the sale. If the callback shows an error, the usual causes are a redirect URI that does not match exactly, or an http:// address.

Xero

Integrations → Xero. Pushes customers as contacts and sales as invoices (and their payments) to a Xero organisation.

/next/integrations/xero
Xero integration
Xero.
  1. Create a Xero app

    On developer.xero.com → My Apps → New app, type Web app, with the redirect URI https://your-domain/xero/callback. Copy the Client ID and generate a Client Secret.

  2. Enter them and connect

    Paste both, save, press Connect and pick the organisation (with several authorised, the first is used). Test Connection shows its name.

  3. Check the account codes

    Sales account code (default 200) receives invoice lines; Payment account code — a bank account in Xero — receives payments. Leave the payment code empty to send invoices only.

  4. Push customers, then invoices

    Contacts first, so each invoice finds its contact.

Invoices are sent as Authorised, numbered with the sale reference, with shipping, discount and tax as separate lines on the sales account — totals match Stocky, and your accountant can remap those lines in Xero. A sale already in Xero is not sent again. With Auto-sync new sales on, each new sale is sent in the background (background queue cron line). Xero's connection expires after 60 days without use; the keep-alive line prevents that. Because invoice numbers are sale references, Xero rejects a sale it already has even after the links are reset.

Google Sheets

Integrations → Google Sheets. Writes sales, products and customers into a Google spreadsheet you own — one tab each, rewritten on every export. A snapshot, not a live feed.

  1. Set up Google Cloud

    On console.cloud.google.com, create a project and enable the Google Sheets API (APIs & Services → Library). Configure the OAuth consent screen as External.

  2. Create the OAuth client

    Credentials → Create credentials → OAuth client ID, type Web application, authorised redirect URI https://your-domain/google-sheets/callback.

  3. Connect and pick the sheet

    Paste the Client ID and Secret, save, press Connect Google account. Then Create new (makes “Stocky Export”) or paste the URL of a sheet your account can edit, and run the exports.

Publish the consent screen. While it stays in Testing, add your account as a test user — and expect the connection to die after 7 days, because Google expires test-mode refresh tokens. Published, it lasts until you revoke it.

Keep the page open while an export runs, until its counter stops. Switch on Auto-export nightly and add the Google Sheets cron line to refresh every tab at 02:30. If connecting fails with “no refresh token”, remove the app under your Google account's third-party access and connect again.

Mailchimp

Integrations → Mailchimp. Sends customers to a Mailchimp audience, so newsletters go out from Mailchimp rather than your own mail server.

  1. Create an API key

    In Mailchimp: Account → Extras → API keys → Create a key. It ends in -us… (your data centre) — paste the whole thing.

  2. Choose the audience

    Paste the key, press Load audiences, pick one, decide on double opt-in (on by default: new contacts get a confirmation email first) and save. Test Connection pings Mailchimp.

  3. Push customers, then switch on auto-sync

    Push customers adds or updates everyone with an email, with first name, last name and phone; existing members keep their subscription status. Auto-sync then adds each new customer as they are created — in the background, so it needs the background queue cron line.

Only push people who agreed to marketing email. Mailing customers who never opted in can breach GDPR or CAN-SPAM and get the Mailchimp account suspended. Keep double opt-in on if you are unsure.

Telegram

Integrations → Telegram. Sends a message to a Telegram chat, group or channel for each sale, purchase, payment, expense or other event you choose. The Guide tab repeats these steps with this server's cron line filled in.

  1. Create the bot

    In Telegram, open @BotFather, send /newbot, choose a name and a username, and copy the bot token it replies with (123456789:ABC…).

  2. Find the chat ID

    Your own chat: send the bot any message first (a bot cannot start a conversation), then ask @userinfobot for your ID. A group: add the bot. A channel: add the bot as an administrator. For a group or channel, post a message there and open https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates — the "chat":{"id": …} value is the chat ID, negative for groups and channels; copy the minus sign too.

  3. Connect

    Paste the token and chat ID on the Settings tab, choose All events or only some (sale.created, purchase.created, payment.created, expense.created, cash_register.opened…), switch it on, save, and press Send test message.

Anything saved in Stocky — at the POS or in the admin — is sent right after it is saved, with its final totals; no cron and no queue worker, and the cashier never waits for Telegram. A save that is cancelled sends nothing. Two kinds of message wait on Telegram's own queue instead: a send that failed, retried up to three more times over the next few minutes, and events raised in the background, such as orders imported from WooCommerce or Shopify. The telegram:send cron line sends them, and nothing else; the Guide tab shows how many are waiting — a number that keeps growing means that line is not running.

ErrorFix
HTTP 401 UnauthorizedWrong bot token — copy it again from BotFather.
HTTP 400 chat not foundWrong chat ID, or the bot is not in the group. For a personal chat, message the bot first.
HTTP 403 bot is not a member / was kickedAdd the bot back — as an administrator for a channel.
The test works, sales do notThe event is not ticked, or the switch is off.

Slack

Integrations → Slack. Posts the same one-line event messages to a Slack channel — 🛒 New sale — Ref: SL_0042 · Total: 125.50 · Status: completed.

  1. Create an incoming webhook

    In Slack, create an app with Incoming Webhooks switched on (see api.slack.com/messaging/webhooks), add a webhook to the channel, and copy its URL — it starts with https://hooks.slack.com/.

  2. Connect

    Paste the URL, choose all events or some, switch it on, save, and press Send test message. The URL is stored write-only: afterwards only its last characters are shown.

The test goes out at once; event messages are sent in the background and need the background queue cron line. A failed send is written to the application log.

WhatsApp Business

Integrations → WhatsApp, through Meta's WhatsApp Cloud API: send invoices, payment receipts and order updates to customers' phones, and see what was delivered and read. Tabs: Connection, Automations, Delivery log, Setup guide.

  1. Create the Meta app

    On developers.facebook.com/apps, create a Business app and add the WhatsApp product. From WhatsApp → API Setup, copy the Phone number ID (a long number — not the phone number itself) and the WhatsApp Business Account ID.

  2. Create a permanent token

    The token on API Setup expires after 24 hours. In Business Settings → System users, add an admin system user, assign it the WhatsApp account (full control) and the app, and Generate new token with whatsapp_business_messaging and whatsapp_business_management. Copy the App Secret from App settings → Basic as well.

  3. Connect

    Enter the phone number ID, account ID, token, app secret and your default country code (added to numbers that start with 0), save, and press Test Connection — it shows the number, its verified name and quality rating.

  4. Register the webhook

    In Meta: WhatsApp → Configuration → Webhook → Edit. Paste the Callback URL (https://your-domain/api/whatsapp/webhook) and the Verify Token shown on the Connection tab, Verify and save, then under Manage subscribe to messages. Meta only accepts https:// addresses.

  5. Test, then switch on

    Send a test message (in development mode, add the recipient under API Setup → To first). When it arrives, turn on Enable WhatsApp sending and choose your automations.

AutomationSent whenPlaceholders
Sale createdA sale is saved{contact_name} {business_name} {invoice_number} {invoice_url} {total_amount} {paid_amount} {due_amount}
Payment receivedA payment is recorded ({paid_amount} is that payment)
Order confirmed / shipped / deliveredAn online-store order reaches that status{contact_name} {business_name} {order_number} {total_amount} {status}

Each automation has its own switch and editable text, sent to the customer's phone number (nothing is sent to a customer without one). Sales, quotations and purchases also get a WhatsApp action that sends through the API directly. Automations are delivered in the background — add the background queue cron line. The Delivery log shows every message as queued, sent, delivered, read, failed or received, with Retry for failed ones.

The 24-hour window. WhatsApp only delivers free-form messages to people who wrote to your number in the last 24 hours. Outside it, sends fail with error 131047. The delivery log explains each Meta error code and its fix.

Webhooks

Integrations → Webhooks. For systems this guide has not heard of — your own app, Zapier, Make or n8n. A webhook is a URL of yours that Stocky calls with a JSON payload whenever a chosen event happens, signed with a secret so your side can check it came from Stocky.

/next/settings/webhooks
Webhooks
Webhooks with their events and the delivery log — payload, headers, response and status.
  1. Add a webhook

    A name, your HTTPS URL, the events (or All), a timeout (15 seconds by default, 60 at most) and Active. A secret starting whsec_ is generated; it is shown in the edit window, with Regenerate.

  2. Test it

    The lightning button sends a webhook.test event. Like every delivery it goes through the background queue, so it arrives within a minute when that cron line runs.

Events: sale.created / updated / deleted, sale_return.created / updated / deleted, purchase.created / updated / deleted, purchase_return.created / updated / deleted, payment.created / deleted, payment_purchase.created / deleted, payment_sale_return.created / deleted, payment_purchase_return.created / deleted, expense.created / updated / deleted, cash_register.opened and client.created.

Each call is a POST with this body:

{
  "id": "4f0c7c9e-…",            // unique per delivery
  "event": "sale.created",
  "created_at": "2026-10-03T14:05:22+00:00",
  "data": {
    "id": 1042,
    "type": "Sale",
    "attributes": { "Ref": "SL_1042", "GrandTotal": 125.5, "statut": "completed", … }
  }
}

…and these headers: X-Webhook-Event, X-Webhook-Id (the webhook), X-Webhook-Delivery (this delivery), X-Webhook-Attempt and X-Webhook-Signature — sha256= followed by the hex HMAC-SHA256 of the raw body, keyed with the webhook's secret. Verify it before trusting the payload:

$body      = file_get_contents('php://input');
$expected  = 'sha256=' . hash_hmac('sha256', $body, 'whsec_your_secret');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

if (! hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

Answer with any 2xx status. Anything else — or no answer within the timeout — is retried after 1 minute, 5 minutes, 30 minutes and 2 hours; after the fifth attempt the delivery is marked failed. The Delivery Logs tab shows each one as pending, retrying, success or failed, with the payload, the response code and body, and the time taken. Use X-Webhook-Delivery to ignore a delivery you have already processed.

Google Calendar & payment gateways

Mobile app & API

Stocky's admin, POS, store, customer display and portal are all installable web apps (PWAs). A native companion app is sold separately; this package holds its server side.

/next/settings/mobile-app
Mobile app settings
Mobile app settings: switch, branding, modules and behaviour.

Settings → Mobile App: enable or disable sign-in from the app (with a maintenance message when it is off), the app name, logo, primary colour and theme mode, which modules it shows, whether the scanner, offline data and price editing are allowed, the minimum app version that may connect, and support contacts.

The API

The app authenticates at POST /api/mobile/login with an email and password and receives a Laravel Passport personal access token, sent on every later call as Authorization: Bearer …. GET /api/mobile/ping lets a client validate a server URL before signing in. The token carries the user's role, so the app sees exactly what the browser would.

The rest of the API — the endpoints the admin itself uses under /api/… — accepts the same Bearer token, which is how your own integrations read products, create sales or pull reports. Tokens issued to devices are listed, and can be revoked, under Settings → Login Devices.

Every endpoint — path, parameters, validation rules, required permission, response shapes and cURL / JavaScript / PHP samples — is documented in the API reference, which ships with this package. It also exposes an OpenAPI 3 document you can import into Postman or Insomnia, and a try-it console that sends real requests against your own server.

Dashboard

The first page after sign-in. A date range — today, 7 days, this month, this year or a custom period — and a warehouse filter at the top; everything below follows them.

/next/dashboard
Dashboard
The dashboard for the current month.

Which widgets show and in what order is set in System Settings → Dashboard, and the default range too, so a stock keeper can open on alerts and a manager on profit. The Today's summary drawer in the header is the short version, available from any page.

Reports

Reports. Sixty screens, each the same shape: a date range with quick picks (today, 7 days, 30 days, 90 days, this year), a warehouse filter where it applies, a chart where one helps, a table, and Excel and PDF export. Reports default to today; pick a range first.

/next/reports/sales
Sales report
The sales report: payment status, sales over time and the invoice table under one date range.
GroupReports
Sales & purchasesSales, Purchases, Sales Return, Purchases Return, Product Sales, Products Sold Summary, Product Purchases, Sales by Category, Sales by Brand, Discount Summary, Draft Invoices, Return Ratio, Transactions.
PaymentsPayments on sales, purchases, sales returns and purchases returns; Cash Flow; Cash Register.
ProfitProfit and Loss; profit by product, category, unit, customer, date and warehouse.
StockStock, Stock Detail, Warehouse, Quantity Alerts, Negative Stock, Dead Stock, Zero Sales, Stock Aging, Inventory Valuation (summary and detail), Stock Transfer, Stock Adjustment, Internal Location, Expiry, Batch Register, Batch History, the four serial reports, Warranty & Guarantee.
PeopleCustomers, Top Customers, Inactive Customers, Loyalty Points, Suppliers, Top Suppliers, Sellers, Users, Login Activity; per-customer, per-supplier and per-user detail reports.
MoneyExpenses, Deposits, Tax Summary.
ModulesAttendance Summary, Service Jobs, Checklist Completion, Customer Maintenance History, Kitchen, and the reports inside each business module.
SystemError Logs — the application log, readable without a shell.
/next/reports/profit-and-loss
Profit and loss report
Profit and loss.
/next/reports/stock-aging
Stock aging report
Stock aging.
/next/reports/inventory-valuation-summary
Inventory valuation
Inventory valuation.
/next/reports/top-selling-products
Top selling products
Top-selling products.

Analytics, 3D & AI reports

/next/reports/analytics
Analytics report
Analytics: the business in one page.
/next/reports/sales-3d-dashboard
3D sales dashboard
The 3D sales dashboard.

Analytics is a one-page summary — revenue, margin, growth against the previous period, best sellers, best customers — for a manager who wants one screen. The 3D sales dashboard is the same data drawn for a wall screen.

/next/reports/ai-reports
AI reports
AI reports: pick a question, get the answer from your own data.

AI Reports answers a fixed list of business questions — what sells best on weekends, which customers are slipping, which products are about to run out — from your own database. Nothing is sent to a third-party model and no API key is needed; the name describes the questions, not a chatbot. See Deliberately not here.

Email, SMS & notifications

Mail

/next/settings/mail
Mail settings
Mail settings with a test button.

Settings → Mail Settings. Mailer (SMTP), host, port, encryption, username, password, sender name and address. Send a test before relying on it. Everything Stocky emails — invoices and quotations from a document, portal invitations, store verification and password resets, order confirmations — goes through this.

SMS and WhatsApp

Settings → SMS Settings: Twilio, Termii, Infobip or a custom HTTP gateway (URL, method, parameter names), with the default gateway in System Settings. SMS Templates hold the text sent for a sale, a purchase, a quotation, a return and a payment, with placeholders such as the customer name, the reference and the amount. WhatsApp templates live under Marketing and use the same placeholders.

/next/settings/sms-templates
SMS templates
SMS templates.
/next/settings/email-templates
Email templates
Email templates for sales, purchases and quotations.

In-app

The bell in the header collects stock alerts, new online orders, kitchen tickets, sync results and approvals. Slack and Telegram can receive the same alerts (see Telegram and Slack). Settings → Custom Fields adds your own fields to products, customers, suppliers and documents, and they appear on the forms, the PDFs and the templates.

Languages & translations

Settings → Languages. Twenty-four languages ship: English, French, Arabic, Turkish, Thai, Hindi, German, Spanish, Italian, Indonesian, Simplified and Traditional Chinese, Russian, Vietnamese, Korean, Bangla, Portuguese, Danish, Japanese, Polish, Swahili, Hausa, Yoruba and Amharic. Enable the ones you want offered; set the default in System Settings. Arabic runs the admin, the POS and the store right-to-left.

/next/settings/languages
Languages
Languages: enable, set a flag, add a new one.
/next/settings/translations/fr
Translation editor
The translation editor.

Strings live in the database, not in files, so Translations edits them from the panel: search a key or a phrase, type the translation, save. A language you add from the panel starts as a copy of English and is translated the same way. Product names and descriptions can be translated per language on the product form for the store; the customer portal and the store each have their own language switcher.

Appearance & PWA

Settings → Appearance: the login page and sidebar branding, the accent colours, the sidebar style — default, large, flat or dark — the default theme mode, and the sidebar menu manager, which hides, renames and reorders entries for everyone (permissions still apply on top). Reset to default undoes it.

/next/settings/appearance
Appearance settings
Appearance.

Each user's own choice — light or dark, sidebar layout — is the gear button bottom right and is saved in their browser. Settings → PWA holds the install manifests described under Branding, SEO & PWA.

Backups

Settings → Backup. Generate backup dumps the database to storage/app/public/backup/; the list shows every dump with its date and size, to download or delete. With the cron entry in place the database:backup command runs on the schedule as well.

/next/settings/backup
Backup page
Backups: generate, download, delete; cloud backup to S3 or Google Drive.

Cloud backup copies each dump off the server: Amazon S3 (or any S3-compatible bucket — key, secret, region, bucket, endpoint, path) or Google Drive (client ID and secret, refresh token, folder ID). A backup that lives only on the server it protects is not a backup.

The dump is the database only. Product images, attachments and documents live in public/images/ and storage/app/ — include those folders in your file backup. To restore, import the SQL into an empty database with phpMyAdmin or mysql, and copy the folders back. There is no restore button in the panel, on purpose: restoring overwrites everything.

System health & security

/next/settings/system-health
System health
System health.
/next/settings/login-devices
Login devices
Login devices.

System Health: PHP and Laravel versions, environment, database size, storage usage, the queue status (pending jobs — a growing number means the scheduler is not running), the last backup date, and a PDF of it all for a support ticket.

Login Devices: every active session and API token with its device, address and last activity; sign out any of them, or all but this one. The Login Activity report keeps the history. Passwords are reset from the login page by email; the storefront's request-safety middleware rate-limits and screens form submissions.

Cron & queue

Stocky works without either — sales, stock, receipts, the store and the reports need nothing in the background. A single cron entry unlocks the scheduled work:

* * * * * cd /path/to/stocky && php artisan schedule:run >> /dev/null 2>&1

On cPanel this is Cron Jobs; use the full path to PHP 8.2+ if php is older. If you would rather schedule only the integrations you use, each has a cron line of its own — see Cron lines at a glance; use one style or the other, not both. What the scheduler runs:

WhenWhat
Every minuteMeeting reminders; scheduled marketing campaigns; queued Telegram notifications (retries and imported orders — can equally be given a cron entry of its own, php artisan telegram:send; see Telegram); the queue worker — one pass over the default, webhooks and sync queues (emails, webhooks, marketplace syncs, Xero and Mailchimp auto-sync).
Every 5 minutesShopify: whichever steps of each connected shop's plan are due (see Shopify). Nothing runs on the ticks where nothing is due. This one can equally be given a cron entry of its own — php artisan shopify:sync — if you would rather schedule each integration separately.
Every 15 minutesWooCommerce: pull orders. Couriers: status checks for shipments still on the way, at the interval set in Courier Settings; old courier logs are pruned (see Couriers).
HourlyWooCommerce: push stock.
DailyDatabase backup; assets due for validation; keep-alive for Salla and Xero connections; WooCommerce: push unsynced products (02:00), pull product changes (03:00), customers (03:30); Google Sheets auto-export (02:30).

The queue driver is database, so there is nothing to install and no Redis. Because the scheduler drains the queue each minute, you do not need a separate queue:work process; if you run one anyway (Supervisor, a systemd unit), the scheduler's pass simply finds nothing to do. Without any cron, queued jobs drain inline while somebody uses the admin, which is enough for a small shop but delays webhooks and syncs until the next visit.

Troubleshooting

SymptomCause and fix
A blank or broken page after an updateThe browser is serving old files. Hard-refresh (Ctrl + Shift + R) or clear the site's cache. If the admin is installed as a PWA, close and reopen it.
500 error or a white pageRead storage/logs/laravel.log or Reports → Error Logs. Usually a permission on storage/ or bootstrap/cache/, or a missing PHP extension after a hosting change.
/setup is reachable on a live siteThe seal file storage/app/public/installed is missing. Recreate it (any content) and check the folder's permissions.
Images do not upload or showpublic/images/ is not writable, or upload_max_filesize / post_max_size in PHP is below the file size. Product images default to a maximum of 800 px unless resizing is off.
Emails are not sentSettings → Mail Settings → Send test. Most hosts require the sender address to be on your own domain and port 587 with TLS.
The camera scanner or the install prompt does not appearThe site is not on HTTPS. Browsers only allow both on a secure origin.
The POS says Offline while the internet worksThe server is not answering the POS heartbeat — a firewall, a proxy timeout or maintenance mode. Check that the admin loads in another tab. The offline switch itself is in System Settings.
Queued jobs pile up in System Health; webhooks and syncs are lateThe cron entry is missing or points at the wrong PHP. See Cron & queue.
Receipts print with a dialog every timeThat is browser printing. Use QZ Tray or direct network printing for silent printing; see POS settings.
The customer display does not updateThe token expired (24 hours) — generate a new one — or the POS tab is not open on the cashier's side.
Stock differs between the store and the POSThe store sells from the warehouses chosen in Store Settings; the POS from the warehouse selected on the register. Compare the same warehouse.
WooCommerce shows DisconnectedRe-test the connection. The application password may have been revoked, or the WordPress site blocks the REST API for non-logged-in requests.
The wrong day on evening salesThe timezone in System Settings does not match the shop. Change it; existing documents keep their stored time.

Deliberately not here

Every link in the sidebar opens a real screen. A few things a system like this could plausibly do are absent on purpose, and this guide would rather name them than let you find out:

Changelog

5.8

5.8

The full history back to 1.0 is in README.md in the package.

Credits & support

Stocky is built on Laravel with Laravel Passport for API tokens; the admin, POS, customer display and portal are Vue 3 applications with Vue Router, Pinia and Ant Design Vue, charts by ApexCharts and ECharts, icons by Lucide, built with Vite; the storefront is Blade with Alpine.js and Tailwind CSS; silent printing through QZ Tray. Thanks to everyone who maintains them.

Getting help

When you write in, three things turn a slow answer into a fast one: the version and the PDF from Settings → System Health, the exact steps that produced the problem, and the last few lines of storage/logs/laravel.log (or the Error Logs report). A screenshot of the screen you were on helps more than a description of it. Support runs for six months from purchase; updates are free for life.

Stocky documentation · version 5.8
Thank you for buying it.