Skip to main content
Version: 1.x

Architecture

This page explains the technical architecture of WCPOS for developers and advanced users.

Two-Part System

WCPOS is designed as a two-part system:

  1. PHP Plugin: Hosted on your server, this is a relatively small plugin which extends the WooCommerce REST API with POS-specific endpoints.

  2. JavaScript Client: This runs locally in your browser, the desktop app, or the iOS/Android apps.

You can think of it as two separate worlds:

  • The PHP world is where data management happens using WordPress and WooCommerce.
  • The JavaScript world keeps a local, offline-capable copy of the store data your tills need, optimised for fast searching and instant response.
pos-client-woo-server

Data Synchronization

Changed in v1.10.0

v1.10.0 replaces the previous replication layer with a dedicated sync engine. The summary below is the short version — the full explanation lives at How the Sync Engine Works.

The client is local-first: every screen reads and writes the device's local database, and a background sync engine keeps that database and WooCommerce convergent. The engine does not blindly mirror your whole store — it works from what your screens actually need:

  • Change detection: the POS polls a lightweight change log with conditional requests; an idle store answers with a single bodyless 304.
  • Declared demand: a screen declares what it's showing, and the engine decides whether that needs a request or is already answered locally.
  • Seeds and lanes: a bounded catalogue seed, a recent-orders window, and idle-time maintenance lanes fill and verify local data on schedules you can tune per device.
  • Durable writes: sales and edits queue locally and drain to WooCommerce, with visible recovery for anything the server refuses.

What gets synced: products and variations, categories/tags/brands, customers, tax rates, coupons (Pro), and orders. Payment gateways are fetched at checkout.

Architecture Pros and Cons

Good 😊Bad 😟
Searching local data is instantKeeping data in sync is challenging
Cached data available offlineLimited by the WooCommerce REST API
Ability to create better native apps for desktop, iOS, and AndroidWordPress themes and hooks cannot customise the POS app

Local Database

The client stores data in a local database on each device — the web and desktop apps use OPFS (Origin Private File System) storage running in a worker, and the mobile apps use the same on-disk format through a filesystem engine. All platforms share one storage format and recovery tooling. This provides:

  • Persistence: Data survives browser restarts and device reboots
  • Performance: Fast queries without network latency — filtering, sorting, and pagination run inside the storage layer, so only the visible page of rows reaches the UI
  • Offline browsing: Cached data remains accessible without internet

Each site + store + cashier combination gets its own local database, so cashiers and stores never share local data on one device. Upgrades never migrate a local database in place — the app re-downloads from the server, which is always the authoritative copy.

Checkout Architecture

The checkout process uses an iframe/webview that loads the WooCommerce Order Pay page. This approach:

  • Leverages existing payment gateways: Any WooCommerce payment gateway can work in the POS
  • Maintains security: Payment processing happens through WooCommerce's secure infrastructure
  • Reduces complexity: No need to re-implement payment gateway integrations

API Extensions

The PHP plugin extends the WooCommerce REST API with additional endpoints for POS-specific functionality, registered under dedicated wcpos/v1 and wcpos/v2 namespaces — wcpos/v2 carries the v1.10.0 sync surface, which is why the app and plugin versions ship in lockstep. See WooCommerce REST API for an introduction.

The wcpos/v2 namespace

v1.10 introduces the wcpos/v2 REST namespace. Sync lives here, and the shared POS services that were previously served from wcpos/v1 are now served from wcpos/v2 (the wcpos/v1 service routes are pass-throughs to their v2 implementations). The wcpos/v1 routes still register for backward compatibility but are frozen — the current client no longer calls them.

Points that matter if you integrate against these endpoints:

  • The v2 routes always register. The old woocommerce_pos_sync_api_enabled option has been removed; there is no longer a flag that turns the API on or off.
  • Public endpoints. wcpos/v2/site, wcpos/v2/ping, and wcpos/v2/echo are public (used for capability and connectivity probing, including the transport fallbacks for restrictive hosts).
  • Orders are UUID-primary. Order identity on the wire is the UUID; the legacy wooOrderId field has been retired from the order pull envelope. Order metadata is typed on the wire through a single normaliser.
  • Line-item pricing storage is documented for third-party sync compatibility — see How POS price overrides are stored.
  • Default product sort in the POS is now name ascending (previously menu_order, id).
  • Removed legacy methods. Several legacy API\Settings controller methods (for example get_general_settings(), update_access_settings(), get_general_endpoint_args(), remove_license_transient()) have been removed; the class alias survives but those methods do not.
Pro mirrors the split

WCPOS Pro follows the same V1/V2 split — its shared services are promoted to wcpos/v2 while its order data stays frozen at v1. Store-scoped product pricing runs on the v2 lane, and the till's store scope is carried onto order writes so multi-store orders price and tax against the right store. See Pro.