# WCPOS Documentation > WCPOS is a free, open-source Point of Sale (POS) application for WooCommerce. It turns any WooCommerce-powered online store into a fully-featured retail POS system. - [WCPOS Documentation](/index.md) ## category ### developer-reference - [Developer Reference](/category/developer-reference.md) ### managing-your-store - [Managing Your Store](/category/managing-your-store.md) ### troubleshooting - [Troubleshooting](/category/troubleshooting.md) ## coupons Manage and apply WooCommerce coupons in WCPOS, including creating coupons, validation rules, and applying them at the register. - [Coupons](/coupons.md): Manage and apply WooCommerce coupons in WCPOS, including creating coupons, validation rules, and applying them at the register. ### applying-coupons The cashier workflow for applying WooCommerce coupons at the WCPOS register — search, coupon pills, sequential discounts, and resolving validation errors. - [Applying Coupons at the Till](/coupons/applying-coupons.md): The cashier workflow for applying WooCommerce coupons at the WCPOS register — search, coupon pills, sequential discounts, and resolving validation errors. ## customers Manage WooCommerce customers in WCPOS, including customer lookup, editing details, and viewing order history. - [Customers](/customers.md): Manage WooCommerce customers in WCPOS, including customer lookup, editing details, and viewing order history. ## error-codes Reference guide for WCPOS error codes across the sync, auth, checkout, payment, printing, and product domains, with troubleshooting steps. - [Error Codes](/error-codes.md): Reference guide for WCPOS error codes across the sync, auth, checkout, payment, printing, and product domains, with troubleshooting steps. ### api API errors occur when communicating with your WooCommerce server. These errors are prefixed with API and are organized into the following categories: - [API Errors](/error-codes/api.md): API errors occur when communicating with your WooCommerce server. These errors are prefixed with API and are organized into the following categories: ### API01001 What This Means - [API01001: Connection Timeout](/error-codes/API01001.md): What This Means ### API01002 What This Means - [API01002: Connection Refused](/error-codes/API01002.md): What This Means ### API01003 What This Means - [API01003: Connection Reset](/error-codes/API01003.md): What This Means ### API01004 What This Means - [API01004: DNS Resolution Failed](/error-codes/API01004.md): What This Means ### API01005 What This Means - [API01005: SSL Certificate Error](/error-codes/API01005.md): What This Means ### API01006 What This Means - [API01006: Network Unreachable](/error-codes/API01006.md): What This Means ### API01007 What This Means - [API01007: Device Offline](/error-codes/API01007.md): What This Means ### API01008 What This Means - [API01008: Website Unavailable](/error-codes/API01008.md): What This Means ### API02001 What This Means - [API02001: Invalid Credentials](/error-codes/API02001.md): What This Means ### API02002 What This Means - [API02002: Token Expired](/error-codes/API02002.md): What This Means ### API02003 What This Means - [API02003: Token Invalid](/error-codes/API02003.md): What This Means ### API02004 What This Means - [API02004: User Not Authorized](/error-codes/API02004.md): What This Means ### API02005 What This Means - [API02005: Insufficient Permissions](/error-codes/API02005.md): What This Means ### API02006 What This Means - [API02006: API Key Invalid](/error-codes/API02006.md): What This Means ### API02007 What This Means - [API02007: Token Refresh Failed](/error-codes/API02007.md): What This Means ### API02008 What This Means - [API02008: Refresh Token Invalid](/error-codes/API02008.md): What This Means ### API02009 What This Means - [API02009: Refresh Token Expired](/error-codes/API02009.md): What This Means ### API02010 What This Means - [API02010: Auth Required](/error-codes/API02010.md): What This Means ### API03001 What This Means - [API03001: Invalid Request Format](/error-codes/API03001.md): What This Means ### API03002 What This Means - [API03002: Missing Required Parameters](/error-codes/API03002.md): What This Means ### API03003 What This Means - [API03003: Invalid Parameter Value](/error-codes/API03003.md): What This Means ### API03004 What This Means - [API03004: Request Too Large](/error-codes/API03004.md): What This Means ### API03005 What This Means - [API03005: Rate Limit Exceeded](/error-codes/API03005.md): What This Means ### API03006 What This Means - [API03006: Unsupported Method](/error-codes/API03006.md): What This Means ### API03007 What This Means - [API03007: Request Queue Full](/error-codes/API03007.md): What This Means ### API04001 What This Means - [API04001: Invalid Response Format](/error-codes/API04001.md): What This Means ### API04002 What This Means - [API04002: Unexpected Response Code](/error-codes/API04002.md): What This Means ### API04003 What This Means - [API04003: Malformed JSON Response](/error-codes/API04003.md): What This Means ### API04004 What This Means - [API04004: Missing Response Data](/error-codes/API04004.md): What This Means ### API04005 What This Means - [API04005: JSON Recovery Attempted](/error-codes/API04005.md): What This Means ### API04006 What This Means - [API04006: Resource Not Found](/error-codes/API04006.md): What This Means ### API05001 What This Means - [API05001: WooCommerce API Disabled](/error-codes/API05001.md): What This Means ### API05002 What This Means - [API05002: WCPOS Plugin Not Found](/error-codes/API05002.md): What This Means ### API05003 What This Means - [API05003: WCPOS Plugin Outdated](/error-codes/API05003.md): What This Means ### API05004 What This Means - [API05004: WordPress API Disabled](/error-codes/API05004.md): What This Means ### API05005 What This Means - [API05005: Plugin Not Found](/error-codes/API05005.md): What This Means ### API06001 What This Means - [API06001: Invalid URL Format](/error-codes/API06001.md): What This Means ### API06002 What This Means - [API06002: Missing API URL](/error-codes/API06002.md): What This Means ### API06003 What This Means - [API06003: Invalid Site Configuration](/error-codes/API06003.md): What This Means ### AUTH101 Your session ended and you need to sign in again. - [AUTH101: Session expired](/error-codes/AUTH101.md): Your session ended and you need to sign in again. ### AUTH111 The store did not accept the sign-in credentials. - [AUTH111: Credentials rejected](/error-codes/AUTH111.md): The store did not accept the sign-in credentials. ### AUTH121 The signed-in store account does not match the cashier on this till. - [AUTH121: Signed in as wrong user](/error-codes/AUTH121.md): The signed-in store account does not match the cashier on this till. ### AUTH201 Your account does not have permission to perform this action. - [AUTH201: Insufficient role](/error-codes/AUTH201.md): Your account does not have permission to perform this action. ### AUTH301 Another authentication plugin is preventing WCPOS from connecting. - [AUTH301: Auth plugin conflict](/error-codes/AUTH301.md): Another authentication plugin is preventing WCPOS from connecting. ### AUTH311 The WCPOS store route is unavailable. - [AUTH311: Rest route missing](/error-codes/AUTH311.md): The WCPOS store route is unavailable. ### AUTH321 WooCommerce is not active on this site, so WCPOS cannot connect. - [AUTH321: WooCommerce missing](/error-codes/AUTH321.md): WooCommerce is not active on this site, so WCPOS cannot connect. ### AUTH331 This store's WCPOS plugin is too old for this version of the app. - [AUTH331: WCPOS plugin outdated](/error-codes/AUTH331.md): This store's WCPOS plugin is too old for this version of the app. ### AUTH401 A secure connection to this store could not be trusted. - [AUTH401: TLS untrusted](/error-codes/AUTH401.md): A secure connection to this store could not be trusted. ### AUTH411 The store address is missing or not a valid URL. - [AUTH411: Store URL invalid](/error-codes/AUTH411.md): The store address is missing or not a valid URL. ### AUTH421 The store's server is blocking the login token on every channel this app can use. - [AUTH421: Auth token blocked by host](/error-codes/AUTH421.md): The store's server is blocking the login token on every channel this app can use. ### AUTH431 The store's REST API did not answer on any address form this app can use. - [AUTH431: Rest transport blocked](/error-codes/AUTH431.md): The store's REST API did not answer on any address form this app can use. ### AUTH441 The login token is larger than this server accepts. - [AUTH441: Auth token too large](/error-codes/AUTH441.md): The login token is larger than this server accepts. ### AUTH999 Signing in or staying signed in hit an unexpected problem. - [AUTH999: Auth unexpected](/error-codes/AUTH999.md): Signing in or staying signed in hit an unexpected problem. ### CHECKOUT101 Checkout did not finish, and the cart is still safe to retry. - [CHECKOUT101: Checkout failed cart safe](/error-codes/CHECKOUT101.md): Checkout did not finish, and the cart is still safe to retry. ### CHECKOUT111 This change could not be applied to the cart, which is unchanged. - [CHECKOUT111: Cart update failed](/error-codes/CHECKOUT111.md): This change could not be applied to the cart, which is unchanged. ### CHECKOUT201 WCPOS could not confirm whether checkout completed. - [CHECKOUT201: Checkout outcome unknown](/error-codes/CHECKOUT201.md): WCPOS could not confirm whether checkout completed. ### CHECKOUT211 The store returned no checkout result, so the order status is unknown. - [CHECKOUT211: Checkout empty response](/error-codes/CHECKOUT211.md): The store returned no checkout result, so the order status is unknown. ### CHECKOUT301 Checkout cannot continue because a product SKU is duplicated or invalid. - [CHECKOUT301: SKU duplicate](/error-codes/CHECKOUT301.md): Checkout cannot continue because a product SKU is duplicated or invalid. ### CHECKOUT401 Your store calculated different totals for this order than the till showed. - [CHECKOUT401: Totals diverged](/error-codes/CHECKOUT401.md): Your store calculated different totals for this order than the till showed. ### CHECKOUT411 A line on this order has price details the POS could not read, so its amount was taken from the stored totals instead. - [CHECKOUT411: Cart line price basis unreadable](/error-codes/CHECKOUT411.md): A line on this order has price details the POS could not read, so its amount was taken from the stored totals instead. ### CHECKOUT421 This order refers to a tax rate your store no longer has, so its tax may be wrong. - [CHECKOUT421: Order tax rate unknown](/error-codes/CHECKOUT421.md): This order refers to a tax rate your store no longer has, so its tax may be wrong. ### CHECKOUT999 Checkout hit an unexpected problem. - [CHECKOUT999: Checkout unexpected](/error-codes/CHECKOUT999.md): Checkout hit an unexpected problem. ### CLIENT101 WCPOS could not finish starting. - [CLIENT101: App start failed](/error-codes/CLIENT101.md): WCPOS could not finish starting. ### CLIENT111 Syncing is taking longer than expected to start. - [CLIENT111: App start slow](/error-codes/CLIENT111.md): Syncing is taking longer than expected to start. ### CLIENT121 This browser lets only one tab send changes at a time. - [CLIENT121: Multi tab limited](/error-codes/CLIENT121.md): This browser lets only one tab send changes at a time. ### CLIENT131 WCPOS queued too many requests at once and dropped some. - [CLIENT131: Request queue overflow](/error-codes/CLIENT131.md): WCPOS queued too many requests at once and dropped some. ### CLIENT141 Local search returned results that do not match the catalogue; the app attempts an automatic search index rebuild. - [CLIENT141: Search results did not match](/error-codes/CLIENT141.md): Local search returned results that do not match the catalogue; the app attempts an automatic search index rebuild. ### CLIENT142 The search index did not answer in time, so WCPOS searched the catalogue directly instead. - [CLIENT142: Search index did not answer](/error-codes/CLIENT142.md): The search index did not answer in time, so WCPOS searched the catalogue directly instead. ### CLIENT143 The search index could not find a product it should contain; the app attempts an automatic search index rebuild. - [CLIENT143: Search index missed a record](/error-codes/CLIENT143.md): The search index could not find a product it should contain; the app attempts an automatic search index rebuild. ### CLIENT144 A search index rebuild failed, so results may be incomplete while the app retries initialization. - [CLIENT144: Search index rebuild failed](/error-codes/CLIENT144.md): A search index rebuild failed, so results may be incomplete while the app retries initialization. ### CLIENT201 WCPOS ran out of memory and could not finish the operation. - [CLIENT201: Out of memory](/error-codes/CLIENT201.md): WCPOS ran out of memory and could not finish the operation. ### CLIENT211 WCPOS stopped because of a device-level crash. - [CLIENT211: Native crash](/error-codes/CLIENT211.md): WCPOS stopped because of a device-level crash. ### CLIENT999 WCPOS encountered an unexpected error. - [CLIENT999: Unexpected error](/error-codes/CLIENT999.md): WCPOS encountered an unexpected error. ### db Database errors occur when storing or retrieving data in the local database. WCPOS uses a local database to store products, customers, and other data for fast access and offline functionality. These errors are prefixed with DB. - [Database Errors](/error-codes/db.md): Database errors occur when storing or retrieving data in the local database. WCPOS uses a local database to store products, customers, and other data for fast access and offline functionality. These errors are prefixed with DB. ### DB01001 What This Means - [DB01001: Connection Failed](/error-codes/DB01001.md): What This Means ### DB01002 What This Means - [DB01002: Query Timeout](/error-codes/DB01002.md): What This Means ### DB01003 What This Means - [DB01003: Transaction Failed](/error-codes/DB01003.md): What This Means ### DB02001 What This Means - [DB02001: Duplicate Record](/error-codes/DB02001.md): What This Means ### DB02002 What This Means - [DB02002: Record Not Found](/error-codes/DB02002.md): What This Means ### DB02003 What This Means - [DB02003: Constraint Violation](/error-codes/DB02003.md): What This Means ### DB03001 What This Means - [DB03001: Query Syntax Error](/error-codes/DB03001.md): What This Means ### DB03002 What This Means - [DB03002: Invalid Data Type](/error-codes/DB03002.md): What This Means ### DB03003 What This Means - [DB03003: Missing Required Field](/error-codes/DB03003.md): What This Means ### HOST101 The server is blocking the browser's permission check (CORS preflight), so the web app cannot reach it. - [HOST101: Cors preflight blocked](/error-codes/HOST101.md): The server is blocking the browser's permission check (CORS preflight), so the web app cannot reach it. ### HOST111 The server's cross-origin (CORS) configuration is broken, so the browser refuses its responses. - [HOST111: Cors misconfigured](/error-codes/HOST111.md): The server's cross-origin (CORS) configuration is broken, so the browser refuses its responses. ### HOST121 A bot-protection page is answering instead of the store's API. - [HOST121: Bot challenge blocking api](/error-codes/HOST121.md): A bot-protection page is answering instead of the store's API. ### HOST131 A proxy in front of the store rejects the server's responses for having too many headers. - [HOST131: Response headers rejected](/error-codes/HOST131.md): A proxy in front of the store rejects the server's responses for having too many headers. ### HOST141 The host's security filter is blocking product searches. - [HOST141: Search blocked by waf](/error-codes/HOST141.md): The host's security filter is blocking product searches. ### HOST151 A cache in front of the store is replaying one person's API responses to everyone. - [HOST151: Cache shared replay](/error-codes/HOST151.md): A cache in front of the store is replaying one person's API responses to everyone. ### HOST161 The host is rate-limiting this store's tills. - [HOST161: Host rate limited](/error-codes/HOST161.md): The host is rate-limiting this store's tills. ### LICENSE101 Your WCPOS Pro license is not active for this store or device. - [LICENSE101: License not active here](/error-codes/LICENSE101.md): Your WCPOS Pro license is not active for this store or device. ### LICENSE201 WCPOS Pro is disabled because its version does not match WCPOS. - [LICENSE201: Version skew Pro disabled](/error-codes/LICENSE201.md): WCPOS Pro is disabled because its version does not match WCPOS. ### LICENSE301 The updater is not authorized to download WCPOS Pro updates. - [LICENSE301: Updater not authorized](/error-codes/LICENSE301.md): The updater is not authorized to download WCPOS Pro updates. ### LICENSE999 License checking hit an unexpected problem. - [LICENSE999: License unexpected](/error-codes/LICENSE999.md): License checking hit an unexpected problem. ### PAYMENT101 Payment succeeded, but WCPOS could not refresh its status afterward. - [PAYMENT101: Payment ok status check failed](/error-codes/PAYMENT101.md): Payment succeeded, but WCPOS could not refresh its status afterward. ### PAYMENT201 WCPOS could not confirm whether the terminal charged the payment. - [PAYMENT201: Payment outcome unknown](/error-codes/PAYMENT201.md): WCPOS could not confirm whether the terminal charged the payment. ### PAYMENT301 The selected payment gateway is unavailable for this store. - [PAYMENT301: Gateway unavailable](/error-codes/PAYMENT301.md): The selected payment gateway is unavailable for this store. ### PAYMENT401 The payment terminal did not finish pairing with WCPOS. - [PAYMENT401: Terminal pairing incomplete](/error-codes/PAYMENT401.md): The payment terminal did not finish pairing with WCPOS. ### PAYMENT999 Payment handling hit an unexpected problem. - [PAYMENT999: Payment unexpected](/error-codes/PAYMENT999.md): Payment handling hit an unexpected problem. ### PRINT101 Automatic printing did not start for this receipt. - [PRINT101: Autoprint did not start](/error-codes/PRINT101.md): Automatic printing did not start for this receipt. ### PRINT201 WCPOS could not confirm that the print job completed. - [PRINT201: Print job failed](/error-codes/PRINT201.md): WCPOS could not confirm that the print job completed. ### PRINT301 The selected printer cannot be reached. - [PRINT301: Printer unreachable](/error-codes/PRINT301.md): The selected printer cannot be reached. ### PRINT311 This receipt could not be emailed or downloaded. - [PRINT311: Receipt delivery failed](/error-codes/PRINT311.md): This receipt could not be emailed or downloaded. ### PRINT999 Printing hit an unexpected problem. - [PRINT999: Print unexpected](/error-codes/PRINT999.md): Printing hit an unexpected problem. ### PRODUCT101 This product could not be saved to your store. - [PRODUCT101: Product save failed](/error-codes/PRODUCT101.md): This product could not be saved to your store. ### PRODUCT111 This variation could not be added to the product. - [PRODUCT111: Variation add failed](/error-codes/PRODUCT111.md): This variation could not be added to the product. ### PRODUCT201 This product image is unavailable, but the product can still be sold. - [PRODUCT201: Product image unavailable](/error-codes/PRODUCT201.md): This product image is unavailable, but the product can still be sold. ### PRODUCT301 No products matched the current search and filters. - [PRODUCT301: Search no results reason](/error-codes/PRODUCT301.md): No products matched the current search and filters. ### PRODUCT321 More than one product matches this barcode. - [PRODUCT321: Barcode ambiguous](/error-codes/PRODUCT321.md): More than one product matches this barcode. ### PRODUCT401 The displayed stock may be older than the store stock. - [PRODUCT401: Stock stale](/error-codes/PRODUCT401.md): The displayed stock may be older than the store stock. ### PRODUCT411 Barcode scanning settings could not be loaded, so scans may not match products. - [PRODUCT411: Barcode config unavailable](/error-codes/PRODUCT411.md): Barcode scanning settings could not be loaded, so scans may not match products. ### PRODUCT421 This product's variation price data could not be read, so displayed prices may be wrong or missing. - [PRODUCT421: Variable price meta invalid](/error-codes/PRODUCT421.md): This product's variation price data could not be read, so displayed prices may be wrong or missing. ### PRODUCT999 Loading or updating products hit an unexpected problem. - [PRODUCT999: Product unexpected](/error-codes/PRODUCT999.md): Loading or updating products hit an unexpected problem. ### py Payment errors occur during checkout and payment processing. These errors are prefixed with PY and relate to issues with payment cards, gateways, and transactions. - [Payment Errors](/error-codes/py.md): Payment errors occur during checkout and payment processing. These errors are prefixed with PY and relate to issues with payment cards, gateways, and transactions. ### PY01001 What This Means - [PY01001: Payment Declined](/error-codes/PY01001.md): What This Means ### PY01002 What This Means - [PY01002: Insufficient Funds](/error-codes/PY01002.md): What This Means ### PY01003 What This Means - [PY01003: Card Expired](/error-codes/PY01003.md): What This Means ### PY01004 What This Means - [PY01004: Invalid Card Number](/error-codes/PY01004.md): What This Means ### PY02001 What This Means - [PY02001: Payment Gateway Error](/error-codes/PY02001.md): What This Means ### PY02002 What This Means - [PY02002: Payment Timeout](/error-codes/PY02002.md): What This Means ### sy System errors are related to device resources and system configuration. These errors are prefixed with SY and indicate issues with your device or the POS application itself. - [System Errors](/error-codes/sy.md): System errors are related to device resources and system configuration. These errors are prefixed with SY and indicate issues with your device or the POS application itself. ### SY01001 What This Means - [SY01001: Out of Memory](/error-codes/SY01001.md): What This Means ### SY01002 What This Means - [SY01002: Disk Full](/error-codes/SY01002.md): What This Means ### SY01003 What This Means - [SY01003: Permission Denied](/error-codes/SY01003.md): What This Means ### SY02001 What This Means - [SY02001: Invalid Configuration](/error-codes/SY02001.md): What This Means ### SY02002 What This Means - [SY02002: Service Unavailable](/error-codes/SY02002.md): What This Means ### SYNC101 This change could not be saved to the local database and remains only on this device. - [SYNC101: Local DB write failed](/error-codes/SYNC101.md): This change could not be saved to the local database and remains only on this device. ### SYNC111 Local store data is damaged and needs repair before syncing can continue. - [SYNC111: Local DB corrupted](/error-codes/SYNC111.md): Local store data is damaged and needs repair before syncing can continue. ### SYNC121 Your store cannot be reached right now, so changes will stay on this device. - [SYNC121: Sync unreachable](/error-codes/SYNC121.md): Your store cannot be reached right now, so changes will stay on this device. ### SYNC131 Your store returned an error, so this action did not complete. - [SYNC131: Store server error](/error-codes/SYNC131.md): Your store returned an error, so this action did not complete. ### SYNC141 Your store is limiting requests temporarily, so this action will retry later. - [SYNC141: Store rate limited](/error-codes/SYNC141.md): Your store is limiting requests temporarily, so this action will retry later. ### SYNC151 Your store sent a malformed response that WCPOS had to repair before reading. - [SYNC151: Store response malformed](/error-codes/SYNC151.md): Your store sent a malformed response that WCPOS had to repair before reading. ### SYNC161 The local database on this device stopped responding, so actions that need it are paused. - [SYNC161: Local DB unavailable](/error-codes/SYNC161.md): The local database on this device stopped responding, so actions that need it are paused. ### SYNC171 A local database on this device could not be created or removed. - [SYNC171: Local DB setup failed](/error-codes/SYNC171.md): A local database on this device could not be created or removed. ### SYNC181 A local database operation is taking far longer than normal; its outcome is not yet known. - [SYNC181: Local database call stalled](/error-codes/SYNC181.md): A local database operation is taking far longer than normal; its outcome is not yet known. ### SYNC201 This record was rejected by your store and is saved only on this device. - [SYNC201: Record rejected](/error-codes/SYNC201.md): This record was rejected by your store and is saved only on this device. ### SYNC211 This record has a field your store will not accept. - [SYNC211: Record invalid field](/error-codes/SYNC211.md): This record has a field your store will not accept. ### SYNC221 A change on this device clashed with an edit made in your store. - [SYNC221: Record conflict](/error-codes/SYNC221.md): A change on this device clashed with an edit made in your store. ### SYNC301 Some older store changes were skipped and must be downloaded again. - [SYNC301: Sync behind head](/error-codes/SYNC301.md): Some older store changes were skipped and must be downloaded again. ### SYNC311 The data stored on this device is from a different app version and cannot be opened. - [SYNC311: Schema mismatch](/error-codes/SYNC311.md): The data stored on this device is from a different app version and cannot be opened. ### SYNC321 Some records synced, but one or more records did not. - [SYNC321: Sync partial](/error-codes/SYNC321.md): Some records synced, but one or more records did not. ### SYNC331 This record on the device does not match your store and needs local repair. - [SYNC331: Local record diverged](/error-codes/SYNC331.md): This record on the device does not match your store and needs local repair. ### SYNC341 This store now requires a newer version of the POS app. - [SYNC341: App update required](/error-codes/SYNC341.md): This store now requires a newer version of the POS app. ### SYNC401 A background sync task stopped unexpectedly before finishing. - [SYNC401: Sync task crashed](/error-codes/SYNC401.md): A background sync task stopped unexpectedly before finishing. ### SYNC411 This device asked the store for data far more often than normal. - [SYNC411: Demand request flood](/error-codes/SYNC411.md): This device asked the store for data far more often than normal. ### SYNC999 Syncing hit an unexpected problem. - [SYNC999: Sync unexpected](/error-codes/SYNC999.md): Syncing hit an unexpected problem. ## extensions Browse, install, and manage POS extensions from the extension directory. Learn how to create and submit your own extensions. - [Extensions](/extensions.md): Browse, install, and manage POS extensions from the extension directory. Learn how to create and submit your own extensions. ### atum Link WCPOS Pro stores to ATUM Multi-Inventory locations for per-location stock, pricing, and SKUs at the POS. - [WCPOS ATUM Integration](/extensions/atum.md): Link WCPOS Pro stores to ATUM Multi-Inventory locations for per-location stock, pricing, and SKUs at the POS. ### polylang Filter WCPOS products by Polylang language and avoid duplicate translated products in the POS. - [WCPOS Polylang](/extensions/polylang.md): Filter WCPOS products by Polylang language and avoid duplicate translated products in the POS. ### storeapps-smart-coupons StoreApps Smart Coupons store credit compatibility for WCPOS receipts, order notes, and POS balance deductions. - [WCPOS StoreApps Smart Coupons](/extensions/storeapps-smart-coupons.md): StoreApps Smart Coupons store credit compatibility for WCPOS receipts, order notes, and POS balance deductions. ### wp-multilang Filter WCPOS products by WP Multilang language and avoid duplicate translated products in the POS. - [WCPOS WP Multilang](/extensions/wp-multilang.md): Filter WCPOS products by WP Multilang language and avoid duplicate translated products in the POS. ### wpml Filter WCPOS products by WPML language and avoid duplicate translated products in the POS. - [WCPOS WPML](/extensions/wpml.md): Filter WCPOS products by WPML language and avoid duplicate translated products in the POS. ## getting-started ### connect How to connect WCPOS to your WooCommerce store, including login options and troubleshooting connection issues. - [Connecting to Your Store](/getting-started/connect.md): How to connect WCPOS to your WooCommerce store, including login options and troubleshooting connection issues. ### free-vs-pro A side-by-side comparison of WCPOS Free and WCPOS Pro — every feature, payment gateway, and capability so you can decide which one you need. - [Free vs Pro](/getting-started/free-vs-pro.md): A side-by-side comparison of WCPOS Free and WCPOS Pro — every feature, payment gateway, and capability so you can decide which one you need. ### installation Minimum requirements for WCPOS including WordPress, WooCommerce, and PHP versions, supported browsers, and minimum desktop and mobile operating system versions. - [Installation Requirements](/getting-started/installation.md): Minimum requirements for WCPOS including WordPress, WooCommerce, and PHP versions, supported browsers, and minimum desktop and mobile operating system versions. ### offline What works offline in WCPOS, how the local database syncs with WooCommerce, and what happens when connectivity is lost. - [Offline Functionality](/getting-started/offline.md): What works offline in WCPOS, how the local database syncs with WooCommerce, and what happens when connectivity is lost. ### previous-versions How to downgrade WCPOS by installing a previous version of the plugin from WordPress.org. - [Re-Installing a Previous Version of the WCPOS Plugin](/getting-started/previous-versions.md): How to downgrade WCPOS by installing a previous version of the plugin from WordPress.org. ### pro-license If you have purchased the Pro version please follow the steps below to install the plugin. - [Installing WCPOS Pro](/getting-started/pro-license.md): If you have purchased the Pro version please follow the steps below to install the plugin. ### roadmap Where WCPOS is headed — the public roadmap, how to request or vote on features, and the major themes in development. - [Roadmap](/getting-started/roadmap.md): Where WCPOS is headed — the public roadmap, how to request or vote on features, and the major themes in development. ## hardware Connect physical devices to WCPOS — receipt printers, barcode scanners, card readers, and cash drawers. - [Hardware](/hardware.md): Connect physical devices to WCPOS — receipt printers, barcode scanners, card readers, and cash drawers. ### printers Add a receipt printer in WCPOS — one scan covers USB, Bluetooth and Wi-Fi, then a test page confirms it works. - [Receipt Printers](/hardware/printers.md): Add a receipt printer in WCPOS — one scan covers USB, Bluetooth and Wi-Fi, then a test page confirms it works. - [Printer permissions on Android](/hardware/printers/android-permissions.md): Nearby devices, local network access and plain connections — the three Android permissions that make a printer appear or vanish. - [Pairing a Bluetooth receipt printer](/hardware/printers/bluetooth-pairing.md): Why a Bluetooth printer isn't in the chooser — one host at a time, Classic versus Low Energy, and the status sheet. - [Printing from the browser: permissions and certificates](/hardware/printers/browser-permissions.md): Chrome's local network permission, mixed content and self-signed certificates — the three things that stop a browser reaching a printer. - [Connecting a cash drawer to the printer](/hardware/printers/cash-drawer.md): The drawer plugs into the receipt printer, not the till. How to wire it, switch it on, and what to check when it doesn't pop. - [Let the app find printers on your iPad or iPhone](/hardware/printers/ios-local-network.md): On iOS, a denied Local Network permission looks exactly like a printer that's switched off. Where to turn it back on. - [The logo is missing from receipts printed in the browser](/hardware/printers/logo-missing-browser.md): Receipts print fine except for the store logo, and only in a browser tab — a CORS header on your WordPress uploads is what's missing. - [Give the printer a fixed address on the same network](/hardware/printers/network-address.md): Why a Wi-Fi printer isn't found, or stops working after weeks — subnets, guest Wi-Fi, client isolation, and DHCP. - [Receipts in Chinese, Thai, Arabic or Cyrillic](/hardware/printers/non-latin-receipts.md): Question marks or boxes instead of text mean the printer has no characters for your language. Print the receipt as an image instead. - [Epson printed once and then stopped — power-cycle first](/hardware/printers/printed-once-then-stopped.md): An Epson holding a job it will never print refuses every other job too. A power cycle clears it in ten seconds. - [Getting the receipt width right (58 mm, 80 mm, 42 or 48 characters)](/hardware/printers/receipt-width.md): What the test page's ruler tells you about paper width, and which of the four character-width answers to pick. - [Epson Secure Printing: what it blocks and how to turn it off](/hardware/printers/secure-printing.md): New Epson printers ship with Secure Printing on and silently discard receipts. Where the setting is, which ports it blocks, and how to turn it off. - [Epson prints nothing and its web page still works (Server Direct Print)](/hardware/printers/server-direct-print.md): When another service on the Epson owns the print engine, every receipt fails while the printer looks perfectly healthy. - [Printer Setup Wizard](/hardware/printers/setup-wizard.md): Answer a few questions and we'll walk you through connecting your receipt printer step by step — and help you fix it if the test print doesn't work. - [Supported receipt printers](/hardware/printers/supported-printers.md): Which receipt printers are tested, which are expected to work, and which are not supported yet — plus how to report yours. - [USB printer permissions on Linux](/hardware/printers/usb-linux.md): An access error when printing over USB on Linux means the device belongs to root — add a udev rule to hand it to your user. - [USB receipt printers on Windows: install a Generic/Text driver](/hardware/printers/usb-windows.md): Why a USB printer on Windows either prints nothing or spits out a page of symbols, and how a Generic/Text queue fixes it. ### scanners Connect a barcode scanner to WCPOS — camera, keyboard-mode, USB, and Bluetooth scanners across web, desktop, and mobile. - [Barcode Scanners](/hardware/scanners.md): Connect a barcode scanner to WCPOS — camera, keyboard-mode, USB, and Bluetooth scanners across web, desktop, and mobile. - [Scanner Setup Wizard](/hardware/scanners/setup-wizard.md): Answer a few questions and we'll walk you through setting up your barcode scanner — and help you fix it if a scan doesn't come through. ## integrations Third-party WooCommerce plugins that WCPOS works with out of the box, and what to expect from each. - [Integrations](/integrations.md): Third-party WooCommerce plugins that WCPOS works with out of the box, and what to expect from each. ### woocommerce-tax Use WooCommerce Tax automated taxes (TaxJar) with WCPOS: how POS orders get their rates, setup steps, and what to expect at the till. - [WooCommerce Tax](/integrations/woocommerce-tax.md): Use WooCommerce Tax automated taxes (TaxJar) with WCPOS: how POS orders get their rates, setup steps, and what to expect at the till. ## orders View and manage WooCommerce orders in WCPOS, including order history, refunds, and reprinting receipts. - [Orders](/orders.md): View and manage WooCommerce orders in WCPOS, including order history, refunds, and reprinting receipts. ### refunds Issue full or partial refunds for WooCommerce orders directly from WCPOS, with support for refunds back to the original payment method or out of the till as cash. - [Refunds](/orders/refunds.md): Issue full or partial refunds for WooCommerce orders directly from WCPOS, with support for refunds back to the original payment method or out of the till as cash. ## payment Configure payment methods in WCPOS including cash, card, and custom payment gateways like Stripe Terminal and SumUp. - [Payment Methods](/payment.md): Configure payment methods in WCPOS including cash, card, and custom payment gateways like Stripe Terminal and SumUp. ### gateways Payment gateways for WCPOS - [Payment Gateways](/payment/gateways.md): Payment gateways for WCPOS - [Email Invoice Gateway](/payment/gateways/email-invoice.md): Send payment invoices to customers via email in WCPOS - [Mollie Terminal Gateway](/payment/gateways/mollie-terminal.md): Take in-person payments on Mollie Terminal devices in WCPOS - [PayPal Reader (Zettle) Gateway](/payment/gateways/paypal-reader.md): Accept in-person card payments through a PayPal Reader (Zettle) card terminal in WCPOS - [Square Terminal Gateway](/payment/gateways/square-terminal.md): Collect in-person payments on Square Terminal devices in WCPOS - [Stripe Terminal Gateway](/payment/gateways/stripe-terminal.md): Accept payments using Stripe Terminal hardware readers in WCPOS - [SumUp Terminal Gateway](/payment/gateways/sumup-terminal.md): Process payments through SumUp card readers in WCPOS - [Vipps MobilePay Gateway](/payment/gateways/vipps-mobilepay.md): Accept phone-based payments via QR code or push notification in WCPOS - [Web Checkout Gateway](/payment/gateways/web-checkout.md): Complete payments via the web store checkout in WCPOS ## pos Overview of the WCPOS point of sale screen layout — header, product panel, cart, navigation drawer, and which screens are Free vs Pro. - [POS Screen Overview](/pos.md): Overview of the WCPOS point of sale screen layout — header, product panel, cart, navigation drawer, and which screens are Free vs Pro. ### cart Manage the shopping cart in WCPOS including line items, quantities, discounts, fees, and customer selection. - [Cart Panel](/pos/cart.md): Manage the shopping cart in WCPOS including line items, quantities, discounts, fees, and customer selection. - [Cart Discounts](/pos/cart/discounts.md): Apply discounts at the WCPOS register — quick percentage discounts, line-item price changes, and order-level discount fees. - [Cart Line Items](/pos/cart/line-items.md): Edit cart line items in WCPOS including quantities, prices, discounts, and product details with inline editing. - [Open Orders](/pos/cart/open-orders.md): Work with multiple orders simultaneously in WCPOS including parking orders, switching between transactions, and recovering from interruptions. - [Order Actions](/pos/cart/order-actions.md): Access order management features in WCPOS including order notes, meta data, fees, shipping, and discounts. ### checkout Complete sales in WCPOS checkout including payment methods, payment processing, and order completion. - [Checkout](/pos/checkout.md): Complete sales in WCPOS checkout including payment methods, payment processing, and order completion. ### product-panel Browse, search, and add products to cart in the WCPOS product panel. Includes grid/list views and category filtering. - [Product Panel](/pos/product-panel.md): Browse, search, and add products to cart in the WCPOS product panel. Includes grid/list views and category filtering. - [Barcode Scanning](/pos/product-panel/barcode-scanning.md): Set up barcode scanning in WCPOS using USB scanners, camera scanning, or custom barcode fields. - [Meta Data Keys](/pos/product-panel/meta-data-keys.md): Copy custom product meta data onto cart and order line items in WCPOS using the Meta Data Keys setting. - [Search & Filtering](/pos/product-panel/search-filtering.md): Search and filter products in WCPOS by name, SKU, category, tags, and other attributes. - [Variable Products](/pos/product-panel/variations.md): Work with WooCommerce variable products in WCPOS including quick selection, inline expansion, and barcode scanning for variations. ### reconciliation Quick end-of-day close for WCPOS cashiers — count the drawer, run the report, compare cash and card, and sign off. - [End-of-Day Reconciliation](/pos/reconciliation.md): Quick end-of-day close for WCPOS cashiers — count the drawer, run the report, compare cash and card, and sign off. ### refunds Quick guide to issuing a refund during a sale in WCPOS — start the refund, choose where the money goes, and confirm. - [Refunds at the Till](/pos/refunds.md): Quick guide to issuing a refund during a sale in WCPOS — start the refund, choose where the money goes, and confirm. ## products Manage WooCommerce products in WCPOS, including inventory updates, price changes, and stock management. - [Products Management](/products.md): Manage WooCommerce products in WCPOS, including inventory updates, price changes, and stock management. ### pos-only-products Control product visibility between your online store and POS, including POS-only and online-only products. - [POS Only Products](/products/pos-only-products.md): Control product visibility between your online store and POS, including POS-only and online-only products. ### sync How WCPOS downloads and synchronises products from WooCommerce, including sync presets, coverage, and keeping the catalogue fresh. - [Product Synchronisation](/products/sync.md): How WCPOS downloads and synchronises products from WooCommerce, including sync presets, coverage, and keeping the catalogue fresh. ## receipts Customise WCPOS receipts using the template gallery, logicless HTML templates, and thermal printer XML templates. - [Receipts](/receipts.md): Customise WCPOS receipts using the template gallery, logicless HTML templates, and thermal printer XML templates. ### at-checkout Print and email receipts in WCPOS, including printer setup and receipt customisation options. - [Receipts](/receipts/at-checkout.md): Print and email receipts in WCPOS, including printer setup and receipt customisation options. ### cloud-printing Print WCPOS receipts to printers that aren't attached to the till — Star Online, Star CloudPRNT, Epson Server Direct Print, and PrintNode. - [Cloud Printing](/receipts/cloud-printing.md): Print WCPOS receipts to printers that aren't attached to the till — Star Online, Star CloudPRNT, Epson Server Direct Print, and PrintNode. ### customise The easiest way to change how your WCPOS receipt looks — pick a different template, ask AI to tweak it, or edit it by hand. - [Customise Your Receipt](/receipts/customise.md): The easiest way to change how your WCPOS receipt looks — pick a different template, ask AI to tweak it, or edit it by hand. ### html-templates Create and customise logicless HTML receipt templates using Mustache-style placeholders. - [HTML Templates](/receipts/html-templates.md): Create and customise logicless HTML receipt templates using Mustache-style placeholders. ### receipt-data Complete reference for the canonical data contract available in WCPOS receipt templates. - [Receipt Data Reference](/receipts/receipt-data.md): Complete reference for the canonical data contract available in WCPOS receipt templates. ### storefront Let online customers download receipts and invoices from My Account, rendered with your custom WCPOS template. - [Receipts on Your Online Store](/receipts/storefront.md): Let online customers download receipts and invoices from My Account, rendered with your custom WCPOS template. ### thermal-templates Create XML-based receipt templates for ESC/POS thermal printers with Epson and Star support. - [Thermal Printer Templates](/receipts/thermal-templates.md): Create XML-based receipt templates for ESC/POS thermal printers with Epson and Star support. ## reference ### architecture Technical architecture of WCPOS explaining how the POS client communicates with the WooCommerce REST API. - [Architecture](/reference/architecture.md): Technical architecture of WCPOS explaining how the POS client communicates with the WooCommerce REST API. ### fiscal-compliance Where WCPOS stands on fiscal certification (France NF525, Spain VERIFACTU, Norway, Chile) and EU OSS, and the available workarounds. - [Fiscal Compliance & Certification](/reference/fiscal-compliance.md): Where WCPOS stands on fiscal certification (France NF525, Spain VERIFACTU, Norway, Chile) and EU OSS, and the available workarounds. ### gateway-template Create a custom POS-only payment gateway for WCPOS - [Gateway Template](/reference/gateway-template.md): Create a custom POS-only payment gateway for WCPOS ### pos-discounts Developer reference for how WCPOS stores POS line-item price overrides, how they interact with WooCommerce coupons, and the available filters. - [POS Discount Technical Reference](/reference/pos-discounts.md): Developer reference for how WCPOS stores POS line-item price overrides, how they interact with WooCommerce coupons, and the available filters. ### role-endpoint-access Developer reference for which WCPOS REST endpoints are accessible to each default role (administrator, shop_manager, cashier), plus token-expiry behaviour and diagnostic tips. - [Role Endpoint Access](/reference/role-endpoint-access.md): Developer reference for which WCPOS REST endpoints are accessible to each default role (administrator, shop_manager, cashier), plus token-expiry behaviour and diagnostic tips. ### sync-engine Developer reference for the WCPOS sync engine introduced in v1.10.0: scopes, sync lanes, change detection, declared demand, coverage reporting, and the offline write queue. - [How the Sync Engine Works](/reference/sync-engine.md): Developer reference for the WCPOS sync engine introduced in v1.10.0: scopes, sync lanes, change detection, declared demand, coverage reporting, and the offline write queue. ### sync-performance How the WCPOS sync engine protects your server: bounded request ceilings, back-off under pressure, responsiveness guarantees, and the measured numbers behind them. - [Sync Performance and Server Politeness](/reference/sync-performance.md): How the WCPOS sync engine protects your server: bounded request ceilings, back-off under pressure, responsiveness guarantees, and the measured numbers behind them. ### wc-rest-api The WooCommerce REST API is like a set of standardised “channels” that allows store owners to connect their WooCommerce store to other applications and services. - [Understanding the WooCommerce REST API](/reference/wc-rest-api.md): The WooCommerce REST API is like a set of standardised “channels” that allows store owners to connect their WooCommerce store to other applications and services. ## reports View sales reports and analytics in WCPOS, including daily summaries, payment breakdowns, and cashier reports. - [Reports](/reports.md): View sales reports and analytics in WCPOS, including daily summaries, payment breakdowns, and cashier reports. ### reconciliation Cashier-facing end-of-day procedure in WCPOS — count the drawer, run the report, reconcile cash and card, handle variances, and sign off. - [End-of-Day Reconciliation](/reports/reconciliation.md): Cashier-facing end-of-day procedure in WCPOS — count the drawer, run the report, reconcile cash and card, handle variances, and sign off. ## settings Overview of WCPOS settings, including WordPress admin settings, store settings, and application preferences. - [Settings Overview](/settings.md): Overview of WCPOS settings, including WordPress admin settings, store settings, and application preferences. ### store Configure WCPOS store settings including general options, tax, barcode scanning, theme, and keyboard shortcuts. - [Store Settings](/settings/store.md): Configure WCPOS store settings including general options, tax, barcode scanning, theme, and keyboard shortcuts. - [Barcode Settings](/settings/store/barcode.md): Configure barcode scanning settings in WCPOS including scan delay, search actions, and camera scanning options. - [General Settings](/settings/store/general.md): Configure WCPOS store settings including currency display, number formatting, and default order status. - [Keyboard Shortcuts](/settings/store/hotkeys.md): Configure keyboard shortcuts in WCPOS for faster checkout and navigation using customisable hotkeys. - [Tax Settings](/settings/store/tax.md): Configure tax calculation and display settings in WCPOS including tax-inclusive pricing and itemised tax display. - [Theme Settings](/settings/store/theme.md): Customise WCPOS appearance with light, dark, and system themes plus accent colour options. ### wp-admin Configure WCPOS backend settings in WordPress admin including general options, checkout, and user access permissions. - [Settings in the WordPress Admin](/settings/wp-admin.md): Configure WCPOS backend settings in WordPress admin including general options, checkout, and user access permissions. - [Accessing the POS](/settings/wp-admin/access.md): Configure user roles and capabilities for WCPOS access including Administrator, Shop Manager, and Cashier permissions. - [Checkout Settings](/settings/wp-admin/checkout.md): Configure WCPOS checkout settings in WordPress admin including payment gateways and order processing. - [Customer Tax IDs](/settings/wp-admin/customer-tax-ids.md): How WCPOS stores customer tax IDs, detects which plugin's field to write to, and copies tax IDs onto orders at checkout. - [Email Notifications](/settings/wp-admin/email-notifications.md): Control which WooCommerce email notifications fire for POS orders — per-email admin, customer, and cashier toggles in WCPOS settings. - [General Settings](/settings/wp-admin/general.md): Configure WCPOS general settings in WordPress admin including POS-only products, decimal quantities, and barcode fields. - [Sessions](/settings/wp-admin/sessions.md): View active POS login sessions per user and device, and remotely sign devices out of WCPOS. - [Store Tax IDs](/settings/wp-admin/store-tax-ids.md): Configure the business tax identifiers WCPOS prints on POS receipts and invoices, including VAT, ABN, GSTIN, EIN, and company-registry numbers. ## stores Set up and manage multiple store locations in WCPOS, including per-store pricing, ATUM inventory integration, tax rates, and reports. - [Multi-Store](/stores.md): Set up and manage multiple store locations in WCPOS, including per-store pricing, ATUM inventory integration, tax rates, and reports. ### setup Step-by-step guide to creating and configuring a store location in WCPOS Pro — store details, authorized users, tax, pricing, and login behavior. - [Setting Up Stores](/stores/setup.md): Step-by-step guide to creating and configuring a store location in WCPOS Pro — store details, authorized users, tax, pricing, and login behavior. ## support Get help with WCPOS through Discord, email support, or browse troubleshooting guides and FAQs. - [Support](/support.md): Get help with WCPOS through Discord, email support, or browse troubleshooting guides and FAQs. ### logs Access and understand WCPOS logs for troubleshooting, including the Store health activity log, server-side logs, and error codes. - [Logs](/support/logs.md): Access and understand WCPOS logs for troubleshooting, including the Store health activity log, server-side logs, and error codes. ### notifications Understand the in-app notification bell in WCPOS — where announcements, plugin updates, and licence alerts appear. - [Notifications](/support/notifications.md): Understand the in-app notification bell in WCPOS — where announcements, plugin updates, and licence alerts appear. ### performance Optimise WCPOS performance including server configuration, checkout speed, and WooCommerce HPOS migration. - [Performance](/support/performance.md): Optimise WCPOS performance including server configuration, checkout speed, and WooCommerce HPOS migration. - [Checkout Performance](/support/performance/checkout.md): Troubleshoot slow checkout times in WCPOS by analysing execution times and identifying bottlenecks. - [Server Performance](/support/performance/server.md): Optimise WordPress server performance for WCPOS including HPOS, caching, database optimisation, and hosting recommendations. ### store-health The Store health area in WCPOS: sync performance presets and measured server load, per-collection download coverage, recovering refused changes, and the activity log. - [Store Health](/support/store-health.md): The Store health area in WCPOS: sync performance presets and measured server load, per-collection download coverage, recovering refused changes, and the activity log. ### translations How WCPOS is translated — AI-generated from tuned rules and improved by the community. Suggest fixes for the apps and plugin in the wcpos/translations repo, and for these docs in the wcpos/docs repo. - [Contributing Translations](/support/translations.md): How WCPOS is translated — AI-generated from tuned rules and improved by the community. Suggest fixes for the apps and plugin in the wcpos/translations repo, and for these docs in the wcpos/docs repo. ### troubleshooting - [Clear All Local Data](/support/troubleshooting/clear-local-data.md): How to clear the local WCPOS database and trigger a fresh sync from your WooCommerce store. - [Cloudflare](/support/troubleshooting/cloudflare.md): Stop Cloudflare's security checks from blocking the WCPOS app's connection to your store. - [Troubleshooting "There has been a critical error on this website."](/support/troubleshooting/critical-error.md): Fix the WordPress critical error in WCPOS by checking WooCommerce fatal error logs and identifying the cause. - [Plugin Conflicts](/support/troubleshooting/plugin-conflicts.md): Identify and resolve WordPress plugin conflicts affecting WCPOS using systematic troubleshooting methods. - [Troubleshooting "Cannot read properties of undefined (reading 'data')" Error](/support/troubleshooting/response-error.md): Fix the "Cannot read properties of undefined" error in WCPOS caused by empty server responses or plugin conflicts. - [Your Store and the POS Disagree on Totals](/support/troubleshooting/totals-disagree.md): What it means when WCPOS reports that your store changed an order's totals, and how to find the cause. ## Optional - [WCPOS Website](https://wcpos.com): Product website and downloads - [GitHub](https://github.com/wcpos): Source code and issue tracker - [Discord](https://wcpos.com/discord): Community support chat - [WordPress.org plugin](https://wordpress.org/plugins/woocommerce-pos/): Free version on the WordPress plugin directory - [WCPOS Pro](https://wcpos.com/pro): Pro features and licensing --- # Full Documentation Content [WooCommerce REST APIThe WooCommerce REST API is like a set of standardised “channels” that allows store owners to connect their WooCommerce store to other applications and services.](/reference/wc-rest-api.md) [ArchitectureTechnical architecture of WCPOS explaining how the POS client communicates with the WooCommerce REST API.](/reference/architecture.md) [Sync EngineDeveloper reference for the WCPOS sync engine introduced in v1.10.0: scopes, sync lanes, change detection, declared demand, coverage reporting, and the offline write queue.](/reference/sync-engine.md) [Sync PerformanceHow the WCPOS sync engine protects your server: bounded request ceilings, back-off under pressure, responsiveness guarantees, and the measured numbers behind them.](/reference/sync-performance.md) [Role Endpoint AccessDeveloper reference for which WCPOS REST endpoints are accessible to each default role (administrator, shop\_manager, cashier), plus token-expiry behaviour and diagnostic tips.](/reference/role-endpoint-access.md) [Fiscal ComplianceWhere WCPOS stands on fiscal certification (France NF525, Spain VERIFACTU, Norway, Chile) and EU OSS, and the available workarounds.](/reference/fiscal-compliance.md) [POS DiscountsDeveloper reference for how WCPOS stores POS line-item price overrides, how they interact with WooCommerce coupons, and the available filters.](/reference/pos-discounts.md) [Gateway TemplateCreate a custom POS-only payment gateway for WCPOS](/reference/gateway-template.md) --- [Products2 items](/products/.md) [Orders1 item](/orders/.md) [CustomersManage WooCommerce customers in WCPOS, including customer lookup, editing details, and viewing order history.](/customers/.md) [Stores1 item](/stores/.md) [Reports1 item](/reports/.md) --- [Clear Local DataHow to clear the local WCPOS database and trigger a fresh sync from your WooCommerce store.](/support/troubleshooting/clear-local-data.md) [Critical ErrorFix the WordPress critical error in WCPOS by checking WooCommerce fatal error logs and identifying the cause.](/support/troubleshooting/critical-error.md) [Response ErrorFix the "Cannot read properties of undefined" error in WCPOS caused by empty server responses or plugin conflicts.](/support/troubleshooting/response-error.md) [Plugin ConflictsIdentify and resolve WordPress plugin conflicts affecting WCPOS using systematic troubleshooting methods.](/support/troubleshooting/plugin-conflicts.md) [CloudflareStop Cloudflare's security checks from blocking the WCPOS app's connection to your store.](/support/troubleshooting/cloudflare.md) [Totals DisagreeWhat it means when WCPOS reports that your store changed an order's totals, and how to find the cause.](/support/troubleshooting/totals-disagree.md) --- # Coupons Pro Feature The Coupons screen and the ability to apply coupons at the register require [WCPOS Pro](/getting-started/pro-license.md). Free users see a blurred preview of the Coupons screen but cannot view coupon details or apply codes in the cart. The Coupons screen lets you browse and look up your WooCommerce coupons from inside the POS, and the **Add Coupon** button in the cart applies them to the current order. Coupons themselves are still created and managed in WooCommerce — the POS syncs them down and validates them locally for instant feedback at the till. ## Interface Overview[​](#interface-overview "Direct link to Interface Overview") ### Header Actions[​](#header-actions "Direct link to Header Actions") At the top of the screen: * **Search bar** — Find a coupon by code * **Display settings** () — Configure visible columns ### Coupons Table[​](#coupons-table "Direct link to Coupons Table") The main area displays your synced coupons with: * **Code** — The coupon code customers enter * **Description** — Internal description (also used as the receipt label when set) * **Discount Type** — Percentage, fixed cart, or fixed product * **Amount** — The discount value * **Used / Limit** — Times used and overall usage limit * **Expires** — Expiry date, or blank if none * **Actions** — Three-dot menu ### Footer[​](#footer "Direct link to Footer") * Coupon count with sync button (). **Long press** for Clear and Refresh options. ## Coupon Types[​](#coupon-types "Direct link to Coupon Types") WCPOS supports the three standard WooCommerce coupon types: | Type | What it does | Example | | -------------------------- | --------------------------------------------------------- | --------------------- | | **Percentage discount** | Reduces the cart subtotal by a percentage | `10%` off the order | | **Fixed cart discount** | Reduces the cart total by a fixed amount | `$5` off the order | | **Fixed product discount** | Reduces matching product lines by a fixed per-unit amount | `$2` off each T-shirt | All three types respect the same validation rules (expiry, usage limits, product/category restrictions, etc.). ## Creating Coupons[​](#creating-coupons "Direct link to Creating Coupons") Coupons are created in WooCommerce, not in the POS. Go to **WP Admin → Marketing → Coupons → Add coupon**: 1. **Coupon code** — what cashiers type at the register. Codes are case-insensitive. 2. **Description** — internal note. WCPOS uses this as the discount label on receipts when set, so prefer a customer-friendly phrase like "Manager Discount 10%" over an internal code. 3. **Discount type** — percentage, fixed cart, or fixed product. 4. **Coupon amount** — the value of the discount. 5. **Expiry date** — optional. After this date the coupon will be rejected. ### Usage restriction[​](#usage-restriction "Direct link to Usage restriction") | Restriction | What it does | Example | | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | | **Minimum / maximum spend** | Coupon only applies above/below a subtotal threshold | Valid only on orders over `$50` | | **Individual use only** | Prevents this coupon from being combined with any other coupon | "VIP20" can't be stacked with "SALE10" | | **Exclude sale items** | Skips items already on sale (and any line where a cashier has lowered the price at the till — see [POS price overrides](/pos/cart/discounts.md#how-pos-price-changes-interact-with-coupons)) | Clearance items don't get the extra discount | | **Products / Exclude products** | Restrict the coupon to (or away from) specific products | Only applies to "Espresso Beans" | | **Product categories / Exclude categories** | Restrict by category. Misc/custom products created at the POS respect categories assigned through the POS as well | Only applies to the "Drinks" category | | **Allowed emails** | Limit the coupon to specific customer email addresses (supports `*` wildcards) | `*@yourcompany.com` for staff only | ### Usage limits[​](#usage-limits "Direct link to Usage limits") | Limit | What it does | | -------------------------- | -------------------------------------------------------------------------------- | | **Usage limit per coupon** | Total times this code can be used across all customers | | **Usage limit per user** | Times one customer can use it | | **Limit usage to X items** | For fixed-product coupons, cap the number of qualifying items discounted per use | []() Tips for POS use * Create a **"Manager 10%"** coupon (10% off, no minimum spend, no expiry, single-use restriction off) and give the code to managers — staff can apply it at the till for ad-hoc adjustments and you keep a tracked discount in reports. * Create a **"Loyalty $5"** coupon for repeat-customer rewards. * For one-off promotions, set a short expiry date so the code can't be reused later by mistake. * Setting **Description** to the phrase you'd like printed on receipts is the fastest way to brand your discounts. ## Applying a Coupon at the Register[​](#applying-a-coupon-at-the-register "Direct link to Applying a Coupon at the Register") Tap **Add Coupon** in the cart, then type the code or search by description. The coupon validates instantly against synced data and appears as a removable pill above the cart totals. For the full cashier workflow — search, coupon pills, stacking multiple coupons, and resolving validation errors — see **[Applying Coupons at the Till](/coupons/applying-coupons.md)**. ## How Validation Works[​](#how-validation-works "Direct link to How Validation Works") When a code is entered, the POS checks all the same rules WooCommerce would check on the server: * Coupon exists and is not expired * Usage limits aren't exceeded (overall and per-user) * Minimum/maximum spend is met * "Individual use" coupons don't conflict with already-applied coupons * Product/category restrictions match the cart contents * Email restrictions match the selected customer (or are skipped on Guest orders) * Sale items are excluded if **Exclude sale items** is enabled If any check fails, the cashier sees a specific error message (e.g., "This coupon has expired" or "Minimum spend not reached"). The same checks run again on the server when the order is submitted — the local validation is for speed, not for trust. ## Sync Behaviour[​](#sync-behaviour "Direct link to Sync Behaviour") Coupons sync from WooCommerce to the device like other POS data: * New coupons created in WP Admin appear in the POS on the next sync. * Updates to existing coupons (usage count, expiry changes, etc.) sync down automatically. * Coupons are stored in the local database so they remain available offline. If you just created a coupon in WP Admin and don't see it yet, the sync may not have run. From the Coupons screen footer, tap the sync icon () to refresh — long-press for **Clear and refresh** if you need a fresh fetch. ## Connectivity[​](#connectivity "Direct link to Connectivity") * **Applying coupons** works offline because validation is client-side from synced data. * **Completing checkout** can work offline with an offline-capable payment method. The sale queues locally; the server re-validates the coupon and updates its usage count when the order reaches WooCommerce. * **Creating or editing coupons** happens in WP Admin and requires a connection to your WordPress site. ## How Coupons Interact with POS Discounts[​](#how-coupons-interact-with-pos-discounts "Direct link to How Coupons Interact with POS Discounts") When a cashier lowers a line price at the till and a coupon is then applied, the coupon calculates against the **lowered price**, not the original. POS-lowered lines are treated as "on sale" — coupons with **Exclude sale items** enabled will skip them. See [Discounts](/pos/cart/discounts.md#how-pos-price-changes-interact-with-coupons) for more. ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [DiscountsQuick discounts, line-item price changes, and order-level fees](/pos/cart/discounts.md) [ReportsSee coupon usage in your daily reports](/reports/.md) [POS Discount ReferenceDeveloper reference for how POS discounts interact with coupons](/reference/pos-discounts.md) --- # Applying Coupons at the Till Pro Feature Applying coupons at the register requires [WCPOS Pro](/getting-started/pro-license.md). Free users can see the [Coupons](/coupons/.md) screen as a blurred preview but the **Add Coupon** action is disabled in the cart. This page covers the at-counter workflow — finding a coupon, applying it, stacking multiple coupons, and dealing with errors. For coupon types, setup, and validation rules see [Coupons](/coupons/.md); for ad-hoc discounts a cashier creates on the fly see [Cart Discounts](/pos/cart/discounts.md). ## The Add Coupon flow[​](#the-add-coupon-flow "Direct link to The Add Coupon flow") Below the cart line items there's an **Add Coupon** button. Tapping it opens a small input where you can either type a code or search. 1. Tap **Add Coupon** in the cart 2. Start typing — the input doubles as a search across all synced coupons (code and description) 3. Pick the coupon from the suggestion list, or finish typing the code and press **Enter** The coupon validates instantly against your locally-synced data — there's no round-trip to the server — and the discount appears on the cart total. If you change cart contents afterwards (add an item, change a quantity, swap a customer), the discount recalculates automatically. Code vs. search Cashiers who know the code (e.g. "SUMMER10") can type it and hit Enter — fastest path. The search is for when a customer hands over a printed coupon and the staff member doesn't remember the exact code, or when looking up a loyalty discount by customer name. ## Coupon pills in the cart[​](#coupon-pills-in-the-cart "Direct link to Coupon pills in the cart") Each applied coupon appears as a small **pill** in the cart, sitting just above the totals. The pill shows the coupon's description (or code, if no description is set) and the amount it discounted. Tap the **×** on a pill to remove that coupon — the cart total recalculates immediately. Pills stack vertically when more than one coupon is applied. The order shown is the order they were added — and that order matters for [sequential discounts](#sequential-discounts). Receipt labels The pill text is also what prints on the receipt. If you'd like a cleaner label than the raw coupon code (e.g. *"Loyalty Discount"* rather than *"LOYAL10"*), set the **Description** field on the coupon in `WP Admin → Marketing → Coupons`. WCPOS uses the description as the discount label whenever it's set. ## Sequential discounts[​](#sequential-discounts "Direct link to Sequential discounts") You can apply more than one coupon to an order. WooCommerce treats them **sequentially** — each coupon discounts the running subtotal left by the previous one, not the original cart total. ### Worked example[​](#worked-example "Direct link to Worked example") Cart subtotal: **$100.00** | Step | Coupon | Calculation | Running total | | ---- | ------------------------ | ----------- | ------------- | | 1 | `LOYAL10` (10% off) | $100 × 0.90 | **$90.00** | | 2 | `WELCOME5` ($5 off cart) | $90 − $5 | **$85.00** | | 3 | `EXTRA20` (20% off) | $85 × 0.80 | **$68.00** | The order they're applied in changes the final number. Two 10% coupons stack to 19% off the original (not 20%), because the second 10% applies to the already-discounted total. ### When coupons can't stack[​](#when-coupons-cant-stack "Direct link to When coupons can't stack") A coupon configured with **Individual use only** in WooCommerce blocks any other coupon from being applied alongside it. If `SUMMER25` is individual-use: * Apply `SUMMER25` first → adding any other coupon shows *"This coupon cannot be combined with other coupons."* * Apply other coupons first → adding `SUMMER25` shows the same message. Remove the conflicting coupon to apply the other. ### Fixed-product coupons[​](#fixed-product-coupons "Direct link to Fixed-product coupons") A **fixed product discount** coupon (e.g. *$2 off each T-shirt*) only discounts the line items it matches — it doesn't reduce the running subtotal for other coupons. Stacking it with a percentage cart coupon is safe and predictable. ## Removing a coupon[​](#removing-a-coupon "Direct link to Removing a coupon") * Tap the **×** on the coupon pill to remove that single coupon. * Clearing the cart (**More** menu → *Clear cart*) removes all applied coupons. * Removing a line item that was the *only* qualifying item for a product-restricted coupon will auto-remove the coupon and show a brief toast — "Coupon removed: no qualifying items". ## Validation errors and how to resolve them[​](#validation-errors-and-how-to-resolve-them "Direct link to Validation errors and how to resolve them") The POS runs the same validation rules as WooCommerce — see [How Validation Works](/coupons/.md#how-validation-works) for the full list. When a coupon is rejected, the cashier sees a specific message: | Message | What it means | What to do | | ----------------------------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | *"Coupon does not exist"* | The code wasn't found in synced data. | Check spelling. If the coupon was just created in WP Admin, run a sync from the [Coupons](/coupons/.md) screen (long-press the sync icon for **Clear and refresh**). | | *"This coupon has expired"* | Today's date is past the coupon's expiry. | Extend the expiry in WP Admin, or use a different code. | | *"Usage limit reached"* | The coupon's overall usage limit is exhausted. | Raise the limit in WP Admin, or use a different code. | | *"Customer has already used this coupon"* | The selected customer is over the per-user limit. | Switch customers, or raise the per-user limit. | | *"Minimum spend not reached"* | The cart subtotal is below the coupon's minimum. | Add more items or use a different code. | | *"Maximum spend exceeded"* | The cart subtotal is above the coupon's maximum. | Split into separate orders or use a different code. | | *"This coupon cannot be combined with other coupons"* | Either the new coupon or an already-applied one is set to **Individual use only**. | Remove the conflicting coupon, then apply the desired one. | | *"Coupon not valid for items in cart"* | None of the cart items match the coupon's product/category restrictions. | Add a qualifying item, or pick a different coupon. | | *"Coupon not valid for this customer"* | The selected customer's email doesn't match the coupon's **Allowed emails** rule. | Switch to a customer whose email matches, or remove the email restriction. | If a coupon validates locally but the order is rejected at checkout, the server re-ran validation against fresher data — usually the usage limit was hit in another sale during the same shift. Re-apply or pick another. ## Common workflows[​](#common-workflows "Direct link to Common workflows") Manager discount — ad-hoc 10% with a tracked code Create a coupon in `WP Admin → Marketing → Coupons` called something like `MGR10`: * **Discount type:** Percentage discount * **Coupon amount:** 10 * **Usage limit per coupon:** *(blank — unlimited)* * **Individual use only:** off (so it can stack with loyalty / promo codes) * **Description:** *"Manager Discount"* (this is what prints on the receipt) Share the code with managers only. The coupon shows up in WooCommerce reports as a tracked discount, unlike a [POS price override](/pos/cart/discounts.md) which now just lowers the line price. Loyalty reward — repeat-customer $5 off Create `LOYAL5`: * **Discount type:** Fixed cart discount * **Coupon amount:** 5 * **Minimum spend:** 25 *(or whatever your threshold is)* * **Usage limit per user:** 1 *(if the reward is one-time)* * **Description:** *"Loyalty Reward"* At the till, search "loyalty" to find it without having to remember the code. Single-use promo — flyer or print campaign Create one coupon per campaign with **Usage limit per coupon: 1** if it's a single-redemption flyer, or a higher number for a multi-use promo. Set a tight **Expiry date** so the code can't be reused later by mistake. For multi-use promos where each customer should only redeem once, set both **Usage limit per coupon** *and* **Usage limit per user: 1**. Stacking a manager discount on top of a coupon code the customer brought Apply the customer's code first, then the manager code. WooCommerce treats them sequentially — the manager discount calculates against the already-discounted total, which is usually what customers expect. If the customer's coupon is **Individual use only**, the manager code will be rejected. Either remove the customer's coupon first (and re-apply later if needed) or update the customer's coupon in WP Admin to allow stacking. A customer wants to return part of an order and re-ring it with a different coupon Refund the original order first (see [Refunds](/orders/refunds.md)), then start a fresh sale with the new coupon. Coupons are tied to the order at the time of sale — you can't retroactively swap a coupon on a completed order from the POS. The refund returns the usage count to the coupon so it can be applied again on the new order. ## Interaction with POS price changes[​](#interaction-with-pos-price-changes "Direct link to Interaction with POS price changes") If a cashier lowered a line price at the till (a [POS price override](/pos/cart/discounts.md)) and then applies a coupon, the coupon calculates against the **lowered price**, not the original. POS-lowered lines are treated as "on sale", so any coupon with **Exclude sale items** enabled will skip them. This is intentional — it prevents customers being double-discounted by stacking a cashier discount and a coupon against the original price. See [How POS Price Changes Interact with Coupons](/pos/cart/discounts.md#how-pos-price-changes-interact-with-coupons) for the full mechanics. ## Offline behaviour[​](#offline-behaviour "Direct link to Offline behaviour") * **Applying coupons works offline** — validation runs against locally-synced coupon data. * **Completing the sale can work offline** with an offline-capable payment method. The order queues locally; the server re-validates the coupon and updates its usage count when the order reaches WooCommerce. * **A coupon you just created in WP Admin** won't apply at the till until the next sync. From the [Coupons](/coupons/.md) screen footer, tap the sync icon () — long-press for **Clear and refresh** if you need a fresh fetch. --- # Customers Pro Feature The Customers screen requires [WCPOS Pro](/getting-started/pro-license.md). Free users can select existing customers for orders but cannot view the full customer list or edit customer details. The Customers screen provides comprehensive customer management directly within the POS. View, edit, and create customers without switching to the WooCommerce admin. ## Interface Overview[​](#interface-overview "Direct link to Interface Overview") ### Header Actions[​](#header-actions "Direct link to Header Actions") At the top of the screen: * **Search bar** - Find customers by name, email, etc. * **Add Customer** () - Create a new customer * **Display settings** () - Configure visible columns ### Customer Table[​](#customer-table "Direct link to Customer Table") The main area displays customers with: * **Avatar** - Customer profile picture (or placeholder) * **First Name** - Customer's first name * **Last Name** - Customer's last name (sortable) * **Email** - Contact email address * **Billing Address** - Full billing address * **Date Created** - When the customer was added * **Actions** - Three-dot menu ### Footer[​](#footer "Direct link to Footer") * Customer count with sync button (). **Long press** for Clear and Refresh option ## Key Features[​](#key-features "Direct link to Key Features") ### Customer Search[​](#customer-search "Direct link to Customer Search") Find customers quickly by: * First or last name * Email address * Address information Search matches **every word** you type, in any order and across those fields — so "jane paris" finds Jane whose city is Paris. Sorting and filtering run on the server, covering all your customers rather than only those already on the device. ### Add New Customer[​](#add-new-customer "Direct link to Add New Customer") Create customers directly from the POS: 1. Click the icon in the header 2. Fill in customer details 3. Save the new customer The customer is created in WooCommerce and immediately available for orders. ### Edit Customer[​](#edit-customer "Direct link to Edit Customer") Update customer information: 1. Click the three-dot menu on a customer 2. Select **Edit** 3. Modify details (name, email, addresses) 4. Save changes Changes sync to WooCommerce automatically. ## Display Settings[​](#display-settings "Direct link to Display Settings") Click the sliders icon () to customise visible columns. ![Customers Settings](/img/customers-page-settings.png) Customers Display Settings ### Available Columns[​](#available-columns "Direct link to Available Columns") | Column | Description | | -------------------- | -------------------------------------- | | **Image** | Customer avatar | | **ID** | WooCommerce customer ID | | **First Name** | Customer first name | | **Last Name** | Customer last name | | **Email** | Email address | | **Role** | User role (Customer, Subscriber, etc.) | | **Username** | WordPress username | | **Billing Address** | Billing information | | **Shipping Address** | Shipping information | | **Date Created** | When customer was added | | **Date Modified** | Last update | | **Actions** | Edit, Sync, Delete | ## Customer Actions[​](#customer-actions "Direct link to Customer Actions") Click the three-dot menu (⋮) for options: * **Edit** - Modify customer details * **Sync** - Refresh customer from server * **Delete** - Remove from local database note Deleting a customer from the POS only removes them **locally** — the customer remains in WooCommerce and returns on the next sync. If a customer is deleted **in WooCommerce**, the sync removes them from the POS too. ## Default Customer (Guest)[​](#default-customer-guest "Direct link to Default Customer (Guest)") When no customer is selected, orders are placed as **Guest** orders. Guest orders: * Have no customer name, email, or address attached * Cannot be looked up by customer in order history * Are still visible in the Orders screen and WooCommerce admin To avoid Guest orders, select a customer from the Cart Panel before checkout. If your business requires a customer on every order, consider training cashiers to always assign one — there is no built-in setting to enforce this. ## Using Customers in Orders[​](#using-customers-in-orders "Direct link to Using Customers in Orders") To assign a customer to an order: 1. In the [Cart Panel](/pos/cart/.md), click the customer badge 2. Search for the customer by name, email, or phone number 3. Select the customer 4. The customer is now associated with the order Customer information (billing/shipping addresses) is automatically used for the order. ## Synchronization[​](#synchronization "Direct link to Synchronization") Customer data syncs between the POS and WooCommerce: * **Synced across devices** - Changes appear on other devices at their next change check * **WooCommerce integration** - Customers are stored in WooCommerce * **Offline capability** - View customers even when offline ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [Cart PanelSelecting customers for orders](/pos/cart/.md) [OrdersView customer order history](/orders/.md) --- # Error Codes When WCPOS encounters an issue, it displays an error code that helps identify the problem. From **v1.10.0**, codes follow the format **domain + three digits** — for example `SYNC131` or `AUTH311`. The domain names the area of the POS; the number identifies the specific condition. Every code has its own page with what it means, what to do, and what it means for your data. In the POS, error codes appear in **Store health → Logs**: expand a row and use the **Help** link to jump straight to the code's page here. ## Error Domains (v1.10.0+)[​](#error-domains "Direct link to Error Domains (v1.10.0+)") | Domain | Area | Examples | | ---------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | `AUTH` | Login, sessions, and tokens | [AUTH101](/error-codes/AUTH101.md), [AUTH311](/error-codes/AUTH311.md) | | `CHECKOUT` | Completing orders at the till | [CHECKOUT101](/error-codes/CHECKOUT101.md), [CHECKOUT201](/error-codes/CHECKOUT201.md) | | `CLIENT` | The POS app itself and local storage | [CLIENT101](/error-codes/CLIENT101.md), [CLIENT201](/error-codes/CLIENT201.md) | | `LICENSE` | Pro licence activation and validation | [LICENSE101](/error-codes/LICENSE101.md) | | `PAYMENT` | Payment gateways and terminals | [PAYMENT101](/error-codes/PAYMENT101.md), [PAYMENT301](/error-codes/PAYMENT301.md) | | `PRINT` | Receipt printing | [PRINT101](/error-codes/PRINT101.md), [PRINT301](/error-codes/PRINT301.md) | | `PRODUCT` | Product data and catalogue operations | [PRODUCT101](/error-codes/PRODUCT101.md), [PRODUCT401](/error-codes/PRODUCT401.md) | | `SYNC` | Synchronisation between the POS and your store | [SYNC101](/error-codes/SYNC101.md), [SYNC121](/error-codes/SYNC121.md), [SYNC311](/error-codes/SYNC311.md) | Use the sidebar to browse every code in a domain, or search for the code directly. Codes ending in `999` are the domain's catch-all for conditions that don't yet have a specific code. ## Legacy Codes (before v1.10.0)[​](#legacy-codes "Direct link to Legacy Codes (before v1.10.0)") Versions before v1.10.0 used a different scheme: `[DOMAIN][CATEGORY][SPECIFIC_CODE]`, e.g. `API04001` = API (domain) + 04 (response errors) + 001 (invalid response format). If you're running an older version, or reading an old log entry or support thread, these pages still apply: | Domain | Total Codes | Covers | | -------------------------- | ----------- | --------------------------------------------------- | | [API](/error-codes/api.md) | 39 codes | Server communication, authentication, plugin issues | | [DB](/error-codes/db.md) | 9 codes | Local data storage and retrieval | | [PY](/error-codes/py.md) | 6 codes | Payment processing | | [SY](/error-codes/sy.md) | 5 codes | Device resources and configuration | A v1.10.0+ client never emits these codes — if you see one on an up-to-date POS, it's from an old retained log entry or a server-side message. ## Need More Help?[​](#need-more-help "Direct link to Need More Help?") If you're still experiencing issues after following the troubleshooting steps: 1. Check the [Troubleshooting](/support/troubleshooting/response-error.md) section for more detailed guides 2. Join our [Discord community](https://wcpos.com/discord) for support 3. Report issues on [GitHub](https://github.com/wcpos) --- # API Errors API errors occur when communicating with your WooCommerce server. These errors are prefixed with `API` and are organized into the following categories: ## Categories[​](#categories "Direct link to Categories") | Category | Code Range | Description | | ------------------------------------------- | ---------- | -------------------------------------------- | | [Connection](#connection-errors) | API01xxx | Network and connectivity issues | | [Authentication](#authentication-errors) | API02xxx | Login, tokens, and permission issues | | [Request](#request-errors) | API03xxx | Problems with outgoing requests | | [Response](#response-errors) | API04xxx | Problems with server responses | | [Plugin/WordPress](#pluginwordpress-errors) | API05xxx | Issues with WordPress or WooCommerce plugins | | [Configuration](#configuration-errors) | API06xxx | Setup and configuration problems | *** ## Connection Errors[​](#connection-errors "Direct link to Connection Errors") Network and connectivity issues between the POS and your server. | Code | Name | Description | | ------------------------------------ | --------------------- | -------------------------------------------- | | [API01001](/error-codes/API01001.md) | Connection Timeout | The server took too long to respond | | [API01002](/error-codes/API01002.md) | Connection Refused | The server refused the connection | | [API01003](/error-codes/API01003.md) | Connection Reset | The connection was unexpectedly closed | | [API01004](/error-codes/API01004.md) | DNS Resolution Failed | Could not resolve the server address | | [API01005](/error-codes/API01005.md) | SSL Certificate Error | Problem with the site's security certificate | | [API01006](/error-codes/API01006.md) | Network Unreachable | Cannot reach the network | | [API01007](/error-codes/API01007.md) | Device Offline | Your device is not connected to the internet | | [API01008](/error-codes/API01008.md) | Website Unavailable | The website is not responding | ## Authentication Errors[​](#authentication-errors "Direct link to Authentication Errors") Issues with login, sessions, and permissions. | Code | Name | Description | | ------------------------------------ | ------------------------ | ------------------------------------------------ | | [API02001](/error-codes/API02001.md) | Invalid Credentials | Username or password is incorrect | | [API02002](/error-codes/API02002.md) | Token Expired | Your session has expired | | [API02003](/error-codes/API02003.md) | Token Invalid | The authentication token is not valid | | [API02004](/error-codes/API02004.md) | User Not Authorized | You don't have permission to perform this action | | [API02005](/error-codes/API02005.md) | Insufficient Permissions | Your user role lacks required permissions | | [API02006](/error-codes/API02006.md) | API Key Invalid | The WooCommerce API key is not valid | | [API02007](/error-codes/API02007.md) | Token Refresh Failed | Could not refresh your session | | [API02008](/error-codes/API02008.md) | Refresh Token Invalid | The refresh token is not valid | | [API02009](/error-codes/API02009.md) | Refresh Token Expired | The refresh token has expired | | [API02010](/error-codes/API02010.md) | Auth Required | Authentication is required for this action | ## Request Errors[​](#request-errors "Direct link to Request Errors") Problems with the requests sent to the server. | Code | Name | Description | | ------------------------------------ | --------------------------- | ----------------------------------------- | | [API03001](/error-codes/API03001.md) | Invalid Request Format | The request format is not correct | | [API03002](/error-codes/API03002.md) | Missing Required Parameters | Required data is missing from the request | | [API03003](/error-codes/API03003.md) | Invalid Parameter Value | A parameter has an invalid value | | [API03004](/error-codes/API03004.md) | Request Too Large | The request exceeds size limits | | [API03005](/error-codes/API03005.md) | Rate Limit Exceeded | Too many requests in a short time | | [API03006](/error-codes/API03006.md) | Unsupported Method | The HTTP method is not supported | | [API03007](/error-codes/API03007.md) | Request Queue Full | Too many pending requests | ## Response Errors[​](#response-errors "Direct link to Response Errors") Problems with the responses received from the server. | Code | Name | Description | | ------------------------------------ | ------------------------ | ------------------------------------------- | | [API04001](/error-codes/API04001.md) | Invalid Response Format | The server response format is not valid | | [API04002](/error-codes/API04002.md) | Unexpected Response Code | Received an unexpected HTTP status code | | [API04003](/error-codes/API04003.md) | Malformed JSON Response | The JSON response is corrupted or invalid | | [API04004](/error-codes/API04004.md) | Missing Response Data | Expected data is missing from the response | | [API04005](/error-codes/API04005.md) | JSON Recovery Attempted | Attempted to recover from malformed JSON | | [API04006](/error-codes/API04006.md) | Resource Not Found | The requested resource does not exist (404) | ## Plugin/WordPress Errors[​](#pluginwordpress-errors "Direct link to Plugin/WordPress Errors") Issues with WordPress, WooCommerce, or the WCPOS plugin. | Code | Name | Description | | ------------------------------------ | ------------------------ | ------------------------------------ | | [API05001](/error-codes/API05001.md) | WooCommerce API Disabled | The WooCommerce REST API is disabled | | [API05002](/error-codes/API05002.md) | WCPOS Plugin Not Found | The WCPOS plugin is not installed | | [API05003](/error-codes/API05003.md) | WCPOS Plugin Outdated | The WCPOS plugin needs updating | | [API05004](/error-codes/API05004.md) | WordPress API Disabled | The WordPress REST API is disabled | | [API05005](/error-codes/API05005.md) | Plugin Not Found | A required plugin is not installed | ## Configuration Errors[​](#configuration-errors "Direct link to Configuration Errors") Setup and configuration problems. | Code | Name | Description | | ------------------------------------ | -------------------------- | ----------------------------------- | | [API06001](/error-codes/API06001.md) | Invalid URL Format | The URL format is not valid | | [API06002](/error-codes/API06002.md) | Missing API URL | No API URL has been configured | | [API06003](/error-codes/API06003.md) | Invalid Site Configuration | The site configuration is incorrect | --- # API01001: Connection Timeout ## What This Means[​](#what-this-means "Direct link to What This Means") The POS application attempted to connect to your WooCommerce server, but the server took too long to respond. This usually indicates network latency issues or an overloaded server. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Slow internet connection** — Your network connection may be experiencing high latency * **Server overload** — Your WordPress server may be processing too many requests * **Large data requests** — Requesting too much data at once can cause timeouts * **Firewall or proxy delays** — Network security devices may be adding latency ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Your Internet Connection[​](#1-check-your-internet-connection "Direct link to 1. Check Your Internet Connection") Test your internet speed and stability. Try loading your WooCommerce admin panel in a browser to see if it responds slowly. ### 2. Reduce Server Load[​](#2-reduce-server-load "Direct link to 2. Reduce Server Load") If your server is overloaded: * Consider upgrading your hosting plan * Disable unnecessary plugins temporarily * Check for heavy cron jobs or background processes ### 3. Optimise Server Response Time[​](#3-optimise-server-response-time "Direct link to 3. Optimise Server Response Time") Contact your hosting provider about: * Enabling PHP opcache * Increasing PHP memory limits * Using server-side caching ### 4. Increase Timeout Settings[​](#4-increase-timeout-settings "Direct link to 4. Increase Timeout Settings") If your server legitimately needs more time: * Check if your hosting provider allows increasing PHP execution time * Consider using a CDN to reduce latency ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01002](/error-codes/API01002.md) — Connection Refused * [API01008](/error-codes/API01008.md) — Website Unavailable --- # API01002: Connection Refused ## What This Means[​](#what-this-means "Direct link to What This Means") The server actively refused the connection attempt. This is different from a timeout — the server responded, but said "no." ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Server is down** — The web server (Apache/Nginx) may not be running * **Wrong port** — Attempting to connect on the wrong port * **Firewall blocking** — A firewall is blocking the connection * **IP restrictions** — Your IP address may be blocked ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify the Server is Running[​](#1-verify-the-server-is-running "Direct link to 1. Verify the Server is Running") Try accessing your WordPress site directly in a browser. If it's not loading, contact your hosting provider. ### 2. Check the URL Configuration[​](#2-check-the-url-configuration "Direct link to 2. Check the URL Configuration") Ensure you're using the correct URL: * Verify `http://` vs `https://` * Check for typos in the domain name * Confirm the correct port if using a non-standard one ### 3. Check Firewall Settings[​](#3-check-firewall-settings "Direct link to 3. Check Firewall Settings") If you have access to your server: * Verify that port 80 (HTTP) or 443 (HTTPS) is open * Check if your IP is whitelisted * Review any security plugins that may block API access ### 4. Contact Your Hosting Provider[​](#4-contact-your-hosting-provider "Direct link to 4. Contact Your Hosting Provider") They can check: * Server status and logs * Firewall configurations * Whether your IP has been blocked ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01001](/error-codes/API01001.md) — Connection Timeout * [API01006](/error-codes/API01006.md) — Network Unreachable --- # API01003: Connection Reset ## What This Means[​](#what-this-means "Direct link to What This Means") The connection to the server was established but then unexpectedly closed. This typically happens mid-communication when something interrupts the connection. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Server crash** — The server process may have crashed during the request * **Memory limits** — PHP ran out of memory and was killed * **Timeout mid-request** — The server timed out while processing * **Network instability** — Intermittent network issues * **Security software** — Aggressive security settings closing connections ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Server Error Logs[​](#1-check-server-error-logs "Direct link to 1. Check Server Error Logs") Look in your WordPress error logs or hosting control panel for related errors around the time of the reset. ### 2. Increase PHP Memory Limit[​](#2-increase-php-memory-limit "Direct link to 2. Increase PHP Memory Limit") In your `wp-config.php`: ``` define('WP_MEMORY_LIMIT', '256M'); ``` ### 3. Check for Plugin Conflicts[​](#3-check-for-plugin-conflicts "Direct link to 3. Check for Plugin Conflicts") A plugin may be causing PHP to crash: * Temporarily disable plugins * Re-enable one by one to find the culprit ### 4. Review Server Resources[​](#4-review-server-resources "Direct link to 4. Review Server Resources") Contact your hosting provider to check: * PHP process limits * Memory usage at the time of error * Server stability logs ### 5. Test Network Stability[​](#5-test-network-stability "Direct link to 5. Test Network Stability") If on WiFi, try a wired connection. If the issue persists across different networks, it's likely server-side. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01001](/error-codes/API01001.md) — Connection Timeout * [API01002](/error-codes/API01002.md) — Connection Refused --- # API01004: DNS Resolution Failed ## What This Means[​](#what-this-means "Direct link to What This Means") The POS could not convert your website's domain name (e.g., `yourstore.com`) into an IP address. DNS (Domain Name System) is like the internet's phone book — if it can't find the listing, it can't make the connection. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Typo in domain name** — The URL may have a spelling error * **DNS server issues** — Your DNS server is not responding * **Domain expired** — The domain registration may have lapsed * **DNS propagation** — Recent DNS changes haven't propagated yet * **Local DNS cache** — Outdated DNS information cached on your device ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify the Domain Name[​](#1-verify-the-domain-name "Direct link to 1. Verify the Domain Name") Double-check the URL for typos. Try accessing the site in a browser. ### 2. Check Domain Status[​](#2-check-domain-status "Direct link to 2. Check Domain Status") Use a WHOIS lookup to verify: * The domain is still registered * It hasn't expired * DNS records are configured ### 3. Clear DNS Cache[​](#3-clear-dns-cache "Direct link to 3. Clear DNS Cache") **On your device:** macOS: ``` sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder ``` Windows: ``` ipconfig /flushdns ``` ### 4. Try Alternative DNS[​](#4-try-alternative-dns "Direct link to 4. Try Alternative DNS") Switch to a public DNS server like: * Google: `8.8.8.8` and `8.8.4.4` * Cloudflare: `1.1.1.1` ### 5. Wait for DNS Propagation[​](#5-wait-for-dns-propagation "Direct link to 5. Wait for DNS Propagation") If you recently changed DNS settings, wait 24-48 hours for full propagation. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01006](/error-codes/API01006.md) — Network Unreachable * [API06001](/error-codes/API06001.md) — Invalid URL Format --- # API01005: SSL Certificate Error ## What This Means[​](#what-this-means "Direct link to What This Means") There's a problem with your website's SSL/TLS certificate. This certificate is what makes the connection secure (HTTPS). The POS won't connect to sites with invalid certificates to protect your data. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Expired certificate** — SSL certificates need to be renewed periodically * **Self-signed certificate** — Not issued by a trusted authority * **Wrong domain** — Certificate doesn't match the domain name * **Incomplete certificate chain** — Missing intermediate certificates * **Mixed content** — Some resources loaded over HTTP instead of HTTPS ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Certificate Status[​](#1-check-certificate-status "Direct link to 1. Check Certificate Status") Visit your site in a browser and click the padlock icon to view certificate details. Look for: * Expiration date * Issued to (should match your domain) * Issued by (should be a recognized authority) ### 2. Renew Expired Certificate[​](#2-renew-expired-certificate "Direct link to 2. Renew Expired Certificate") If expired: * Most hosting providers offer free Let's Encrypt certificates * Contact your hosting provider to renew * Check if auto-renewal is enabled ### 3. Fix Certificate Mismatch[​](#3-fix-certificate-mismatch "Direct link to 3. Fix Certificate Mismatch") Ensure the certificate covers: * Your exact domain (`yourstore.com`) * WWW variant (`www.yourstore.com`) if used * Consider a wildcard certificate (`*.yourstore.com`) ### 4. Install Missing Intermediate Certificates[​](#4-install-missing-intermediate-certificates "Direct link to 4. Install Missing Intermediate Certificates") Use an SSL checker tool (like SSL Labs) to identify missing certificates. Your hosting provider can help install them. ### 5. Force HTTPS[​](#5-force-https "Direct link to 5. Force HTTPS") In WordPress, ensure: * Site URL uses `https://` * Force SSL is enabled in WooCommerce settings ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01002](/error-codes/API01002.md) — Connection Refused * [API06001](/error-codes/API06001.md) — Invalid URL Format --- # API01006: Network Unreachable ## What This Means[​](#what-this-means "Direct link to What This Means") The POS cannot establish a route to the server. This is a network-level issue — the data packets can't find a path to your server. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Network configuration issues** — Incorrect gateway or routing settings * **ISP problems** — Your internet service provider is having issues * **VPN interference** — A VPN may be routing traffic incorrectly * **Server network issues** — The server's network may be down ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Your Internet Connection[​](#1-check-your-internet-connection "Direct link to 1. Check Your Internet Connection") * Try accessing other websites * Restart your router/modem * Verify you're connected to the network ### 2. Disable VPN Temporarily[​](#2-disable-vpn-temporarily "Direct link to 2. Disable VPN Temporarily") If using a VPN: * Disconnect and try again * Try a different VPN server * Check if the VPN allows access to your server's location ### 3. Check with Your ISP[​](#3-check-with-your-isp "Direct link to 3. Check with Your ISP") Contact your internet service provider if: * Other sites are also unreachable * The issue persists after restarting network equipment ### 4. Verify Server Status[​](#4-verify-server-status "Direct link to 4. Verify Server Status") * Check if your hosting provider reports any network issues * Try accessing your site from a different network (e.g., mobile data) * Use online tools to check if the site is down for everyone ### 5. Check Firewall Settings[​](#5-check-firewall-settings "Direct link to 5. Check Firewall Settings") Ensure your device's firewall isn't blocking outgoing connections to your server. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01007](/error-codes/API01007.md) — Device Offline * [API01002](/error-codes/API01002.md) — Connection Refused --- # API01007: Device Offline ## What This Means[​](#what-this-means "Direct link to What This Means") Your device is not connected to the internet. The POS detected that there's no active network connection. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **WiFi disconnected** — Your device lost its WiFi connection * **Ethernet unplugged** — The network cable is disconnected * **Airplane mode enabled** — All wireless connections are disabled * **Network adapter disabled** — The network interface is turned off ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check WiFi Connection[​](#1-check-wifi-connection "Direct link to 1. Check WiFi Connection") * Verify WiFi is enabled on your device * Ensure you're connected to the correct network * Check the WiFi signal strength ### 2. Check Physical Connections[​](#2-check-physical-connections "Direct link to 2. Check Physical Connections") If using ethernet: * Verify the cable is securely plugged in * Try a different cable or port * Check the network switch/router lights ### 3. Disable Airplane Mode[​](#3-disable-airplane-mode "Direct link to 3. Disable Airplane Mode") Check if airplane mode is accidentally enabled and disable it. ### 4. Restart Network Adapter[​](#4-restart-network-adapter "Direct link to 4. Restart Network Adapter") **Windows:** * Open Network Connections * Right-click your adapter → Disable, then Enable **macOS:** * Turn WiFi off and on from the menu bar * Or: System Preferences → Network → Turn off/on ### 5. Restart Your Device[​](#5-restart-your-device "Direct link to 5. Restart Your Device") Sometimes a simple restart resolves network detection issues. ## Offline Mode[​](#offline-mode "Direct link to Offline Mode") While offline, WCPOS can still: * Browse and search locally cached products * Browse and search locally cached customers * Start new orders and add items to the cart * View previously synced data **Requires connectivity:** * Completing/checking out orders * Creating new customers When connectivity is restored, the POS will automatically resume normal operations. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01006](/error-codes/API01006.md) — Network Unreachable * [API01008](/error-codes/API01008.md) — Website Unavailable --- # API01008: Website Unavailable ## What This Means[​](#what-this-means "Direct link to What This Means") The POS can reach the internet, but your specific website is not responding. The server hosting your WooCommerce store appears to be down or unreachable. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Server maintenance** — Your hosting provider may be performing updates * **Server crash** — The web server has stopped unexpectedly * **Resource limits exceeded** — Your hosting account hit its limits * **DDoS attack** — The server is overwhelmed by malicious traffic * **Domain/hosting expired** — Your hosting or domain has lapsed ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify the Site is Down[​](#1-verify-the-site-is-down "Direct link to 1. Verify the Site is Down") Try accessing your site directly in a browser. If it doesn't load, the issue is server-side. ### 2. Check Hosting Provider Status[​](#2-check-hosting-provider-status "Direct link to 2. Check Hosting Provider Status") * Visit your hosting provider's status page * Check for scheduled maintenance * Look for reported outages ### 3. Review Hosting Account[​](#3-review-hosting-account "Direct link to 3. Review Hosting Account") Log into your hosting control panel: * Check if your account is active * Verify you haven't exceeded resource limits * Look for any suspension notices ### 4. Contact Hosting Support[​](#4-contact-hosting-support "Direct link to 4. Contact Hosting Support") If everything looks normal on your end, contact your hosting provider. They can: * Check server status * Review server logs * Restart services if needed ### 5. Wait and Retry[​](#5-wait-and-retry "Direct link to 5. Wait and Retry") If it's a temporary outage: * Wait 15-30 minutes * The POS will automatically retry connections * Cached data remains available offline ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API01001](/error-codes/API01001.md) — Connection Timeout * [API01002](/error-codes/API01002.md) — Connection Refused --- # API02001: Invalid Credentials ## What This Means[​](#what-this-means "Direct link to What This Means") The username or password you entered is incorrect. The server rejected the login attempt because the credentials don't match any valid account. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Typo in username or password** — Check for caps lock or extra spaces * **Wrong account** — Using credentials for a different site * **Password recently changed** — The password was updated but the POS has the old one * **Account deleted** — The user account no longer exists ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | --------------------------------------- | ------------------------- | | `woocommerce_rest_authentication_error` | WooCommerce REST API | | `jwt_auth_failed` | JWT Authentication plugin | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify Your Credentials[​](#1-verify-your-credentials "Direct link to 1. Verify Your Credentials") * Double-check your username (usually email or WordPress username) * Verify the password is correct * Try logging into WordPress admin directly to confirm ### 2. Reset Your Password[​](#2-reset-your-password "Direct link to 2. Reset Your Password") If you've forgotten your password: 1. Go to your WordPress login page 2. Click "Lost your password?" 3. Enter your email to receive a reset link 4. Update your password 5. Log into the POS with the new password ### 3. Check the User Account[​](#3-check-the-user-account "Direct link to 3. Check the User Account") In WordPress Admin: * Go to Users → All Users * Verify the account exists * Check that it has appropriate POS access permissions ### 4. Clear Saved Credentials[​](#4-clear-saved-credentials "Direct link to 4. Clear Saved Credentials") In the POS: * Log out completely * Clear any saved/cached login information * Re-enter credentials fresh ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02004](/error-codes/API02004.md) — User Not Authorized * [API02010](/error-codes/API02010.md) — Auth Required --- # API02002: Token Expired ## What This Means[​](#what-this-means "Direct link to What This Means") Your authentication session has expired. For security reasons, login sessions don't last forever. The POS needs to refresh your authentication or you may need to log in again. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Long inactivity** — You haven't used the POS for an extended period * **Server token lifetime** — The server's token expiration is set very short * **Server time mismatch** — Server and device clocks are out of sync ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ------------------------ | ------------------------- | | `jwt_auth_expired_token` | JWT Authentication plugin | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Log In Again[​](#1-log-in-again "Direct link to 1. Log In Again") The simplest solution is to log out and log back in: 1. Log out of the POS 2. Enter your credentials again 3. This creates a fresh session ### 2. Check Token Refresh[​](#2-check-token-refresh "Direct link to 2. Check Token Refresh") The POS should automatically refresh tokens. If it's not working: * Check your internet connection * Verify the server is accessible * See [API02007](/error-codes/API02007.md) if refresh is failing ### 3. Check Server Time[​](#3-check-server-time "Direct link to 3. Check Server Time") Token expiration depends on accurate time: * Ensure your server's clock is correct * Check that your device's time is accurate * Use automatic time sync on both ### 4. Review Token Settings[​](#4-review-token-settings "Direct link to 4. Review Token Settings") If tokens expire too quickly, you may need to adjust server settings (consult your hosting provider or WordPress administrator). ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02007](/error-codes/API02007.md) — Token Refresh Failed * [API02009](/error-codes/API02009.md) — Refresh Token Expired --- # API02003: Token Invalid ## What This Means[​](#what-this-means "Direct link to What This Means") The authentication token being used is not recognized by the server. This is different from an expired token — this token was never valid or has been revoked. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Token revoked** — An administrator revoked the session * **Token corrupted** — Data corruption during storage or transmission * **Server reset** — Server secret keys changed, invalidating all tokens * **Wrong server** — Token from a different WordPress installation ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ------------------------ | ------------------------- | | `jwt_auth_invalid_token` | JWT Authentication plugin | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Log In Again[​](#1-log-in-again "Direct link to 1. Log In Again") Clear your session and authenticate fresh: 1. Log out completely 2. Close and reopen the POS 3. Log in with your credentials ### 2. Clear Application Data[​](#2-clear-application-data "Direct link to 2. Clear Application Data") If logging out doesn't work: * Clear the POS app cache/data * On web: Clear browser cookies and local storage for the site * On desktop: Check app settings for a "Clear Data" option ### 3. Check Server Configuration[​](#3-check-server-configuration "Direct link to 3. Check Server Configuration") If the issue affects all users: * Check if WordPress salts were changed * Verify JWT or authentication plugin settings * Review recent server changes ### 4. Verify You're on the Correct Server[​](#4-verify-youre-on-the-correct-server "Direct link to 4. Verify You're on the Correct Server") Ensure the POS is configured to connect to the right WordPress site, especially if you have multiple installations. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02002](/error-codes/API02002.md) — Token Expired * [API02008](/error-codes/API02008.md) — Refresh Token Invalid --- # API02004: User Not Authorized ## What This Means[​](#what-this-means "Direct link to What This Means") You're logged in, but your user account doesn't have permission to perform the requested action. This is an authorisation issue (what you can do) rather than an authentication issue (who you are). ## Common Causes[​](#common-causes "Direct link to Common Causes") * **User role limitations** — Your WordPress role doesn't include POS access * **POS access disabled** — Your account wasn't granted POS permissions * **Feature restrictions** — Certain features are limited to specific roles * **Store restrictions** — You may not have access to this particular store ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ------------------------------ | -------------------- | | `rest_cannot_view` | WordPress REST API | | `woocommerce_rest_cannot_view` | WooCommerce REST API | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check User Role[​](#1-check-user-role "Direct link to 1. Check User Role") In WordPress Admin → Users: 1. Find your user account 2. Verify the role (e.g., Shop Manager, Administrator) 3. Ensure the role includes WooCommerce capabilities ### 2. Enable POS Access[​](#2-enable-pos-access "Direct link to 2. Enable POS Access") In WordPress Admin → WooCommerce → POS → Access: 1. Find the user or role 2. Enable POS access permissions 3. Save changes ### 3. Request Additional Permissions[​](#3-request-additional-permissions "Direct link to 3. Request Additional Permissions") Contact your store administrator to: * Grant your role POS access * Assign you a role with appropriate permissions * Enable specific features you need ### 4. Check Store Assignment[​](#4-check-store-assignment "Direct link to 4. Check Store Assignment") If using multiple stores: * Verify you're assigned to the correct store * Check store-specific permissions ## Required Permissions[​](#required-permissions "Direct link to Required Permissions") Different actions require different capabilities: * **View products**: Read access to products * **Create orders**: Create/edit order capabilities * **Manage customers**: Customer management capabilities * **Access reports**: View reports capabilities ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02005](/error-codes/API02005.md) — Insufficient Permissions * [API02001](/error-codes/API02001.md) — Invalid Credentials --- # API02005: Insufficient Permissions ## What This Means[​](#what-this-means "Direct link to What This Means") Your user account lacks the specific WordPress capabilities required for this action. While you have basic access, the particular operation you're attempting needs additional permissions. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Limited user role** — Your role doesn't include all needed capabilities * **Capability not assigned** — A specific capability is missing from your role * **Plugin restrictions** — A security plugin is limiting capabilities * **Custom role issues** — Custom roles may be missing capabilities ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | -------------------------------- | ------------------------------ | | `rest_forbidden` | WordPress REST API | | `rest_cannot_create` | WordPress REST API | | `rest_cannot_edit` | WordPress REST API | | `rest_cannot_delete` | WordPress REST API | | `woocommerce_rest_cannot_create` | WooCommerce REST API | | `woocommerce_rest_cannot_edit` | WooCommerce REST API | | `woocommerce_rest_cannot_delete` | WooCommerce REST API | | HTTP 403 | Any server response (fallback) | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Review Required Capabilities[​](#1-review-required-capabilities "Direct link to 1. Review Required Capabilities") Common capabilities needed for POS operations: * `manage_woocommerce` — General WooCommerce management * `edit_shop_orders` — Create and edit orders * `edit_products` — Modify product information * `edit_users` — Manage customer accounts ### 2. Upgrade User Role[​](#2-upgrade-user-role "Direct link to 2. Upgrade User Role") Ask an administrator to assign a more capable role: * **Shop Manager** — Full WooCommerce access * **Administrator** — Full site access ### 3. Add Specific Capabilities[​](#3-add-specific-capabilities "Direct link to 3. Add Specific Capabilities") If you need a custom role, add required capabilities: ``` // Example: Add POS capabilities to a custom role $role = get_role('your_custom_role'); $role->add_cap('manage_woocommerce'); $role->add_cap('edit_shop_orders'); ``` ### 4. Check Plugin Conflicts[​](#4-check-plugin-conflicts "Direct link to 4. Check Plugin Conflicts") Some security or role management plugins may restrict capabilities: * Review plugin settings * Check for capability filters * Temporarily disable to test ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02004](/error-codes/API02004.md) — User Not Authorized * [API02010](/error-codes/API02010.md) — Auth Required --- # API02006: API Key Invalid ## What This Means[​](#what-this-means "Direct link to What This Means") The WooCommerce REST API key being used is invalid. API keys are used for server-to-server authentication, and the key provided doesn't match any valid key in WooCommerce. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Key deleted** — The API key was removed from WooCommerce * **Key typo** — The key was entered incorrectly * **Wrong key pair** — Consumer key and secret don't match * **Key from different site** — Using keys generated for another installation ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify the API Key[​](#1-verify-the-api-key "Direct link to 1. Verify the API Key") In WordPress Admin → WooCommerce → Settings → Advanced → REST API: 1. Check if your API key exists 2. Verify it hasn't been revoked 3. Note the permissions (read/write/read-write) ### 2. Generate New API Keys[​](#2-generate-new-api-keys "Direct link to 2. Generate New API Keys") If the key is missing or invalid: 1. Go to WooCommerce → Settings → Advanced → REST API 2. Click "Add key" 3. Enter a description (e.g., "WCPOS") 4. Select the user 5. Choose "Read/Write" permissions 6. Click "Generate API key" 7. **Copy both the Consumer Key and Consumer Secret** (shown only once!) ### 3. Update POS Configuration[​](#3-update-pos-configuration "Direct link to 3. Update POS Configuration") Enter the new API keys in the POS: * Consumer Key (starts with `ck_`) * Consumer Secret (starts with `cs_`) ### 4. Check Key Permissions[​](#4-check-key-permissions "Direct link to 4. Check Key Permissions") Ensure the key has sufficient permissions: * **Read** — View data only * **Write** — Modify data only * **Read/Write** — Full access (recommended for POS) ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02001](/error-codes/API02001.md) — Invalid Credentials * [API05001](/error-codes/API05001.md) — WooCommerce API Disabled --- # API02007: Token Refresh Failed ## What This Means[​](#what-this-means "Direct link to What This Means") The POS tried to automatically renew your authentication session, but the refresh request failed. This typically means you'll need to log in again. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Refresh token expired** — The refresh token itself has expired * **Refresh token revoked** — An admin invalidated all sessions * **Server error** — The server couldn't process the refresh request * **Network issue** — Connection problem during refresh attempt ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Log In Again[​](#1-log-in-again "Direct link to 1. Log In Again") The most reliable fix: 1. Log out of the POS 2. Log back in with your credentials 3. This creates a fresh session with new tokens ### 2. Check Network Connection[​](#2-check-network-connection "Direct link to 2. Check Network Connection") If refresh is failing due to network issues: * Verify your internet connection * Try accessing your WordPress site in a browser * Wait a moment and try again ### 3. Check Server Status[​](#3-check-server-status "Direct link to 3. Check Server Status") If the server is having issues: * Verify WordPress is running properly * Check for PHP errors in your server logs * Ensure the authentication plugin is active ### 4. Clear Session Data[​](#4-clear-session-data "Direct link to 4. Clear Session Data") If issues persist: * Clear the POS app cache * Remove stored credentials * Start fresh with a new login ## Automatic Token Refresh[​](#automatic-token-refresh "Direct link to Automatic Token Refresh") WCPOS automatically refreshes tokens before they expire to maintain your session. If this process fails repeatedly, there may be a configuration issue that needs attention. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02002](/error-codes/API02002.md) — Token Expired * [API02008](/error-codes/API02008.md) — Refresh Token Invalid * [API02009](/error-codes/API02009.md) — Refresh Token Expired --- # API02008: Refresh Token Invalid ## What This Means[​](#what-this-means "Direct link to What This Means") The refresh token stored by the POS is not recognized by the server. Refresh tokens are used to obtain new access tokens without requiring you to log in again. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Token revoked** — An administrator invalidated your session * **Server secrets changed** — WordPress security keys were updated * **Data corruption** — The token was corrupted in storage * **Multiple logins** — Logging in elsewhere may have invalidated this token ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Log In Again[​](#1-log-in-again "Direct link to 1. Log In Again") Since the refresh token is invalid, you'll need to authenticate again: 1. Log out of the POS 2. Enter your username and password 3. This generates new valid tokens ### 2. Check for Revoked Sessions[​](#2-check-for-revoked-sessions "Direct link to 2. Check for Revoked Sessions") If an admin revoked sessions: * This is normal security practice * Simply log in again * Your new session will work normally ### 3. Check Server Changes[​](#3-check-server-changes "Direct link to 3. Check Server Changes") If this affects all users: * WordPress salts/keys may have changed * JWT plugin settings may have been modified * Contact your server administrator ### 4. Clear Stored Data[​](#4-clear-stored-data "Direct link to 4. Clear Stored Data") If you continue having issues: * Clear the POS application data * Remove cached credentials * Start with a clean login ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02003](/error-codes/API02003.md) — Token Invalid * [API02007](/error-codes/API02007.md) — Token Refresh Failed --- # API02009: Refresh Token Expired ## What This Means[​](#what-this-means "Direct link to What This Means") Your refresh token has exceeded its lifetime and can no longer be used to obtain new access tokens. Unlike access tokens (which expire quickly), refresh tokens typically last days or weeks but do eventually expire. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Extended inactivity** — You haven't used the POS for a long time * **Short token lifetime** — Server configured with short refresh token expiration * **Clock skew** — Device or server time is significantly off ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Log In Again[​](#1-log-in-again "Direct link to 1. Log In Again") When the refresh token expires, you must authenticate again: 1. Log out of the POS 2. Enter your credentials 3. A new refresh token will be issued ### 2. Use POS Regularly[​](#2-use-pos-regularly "Direct link to 2. Use POS Regularly") To avoid this in the future: * Use the POS regularly to keep tokens fresh * Tokens are refreshed automatically when you're active * Extended periods of inactivity will require re-login ### 3. Check Time Settings[​](#3-check-time-settings "Direct link to 3. Check Time Settings") Ensure accurate time on all systems: * Enable automatic time sync on your device * Verify server time is correct * Time differences can cause premature expiration ### 4. Adjust Token Lifetime (Advanced)[​](#4-adjust-token-lifetime-advanced "Direct link to 4. Adjust Token Lifetime (Advanced)") If tokens expire too quickly for your needs, a server administrator can adjust the refresh token lifetime in the authentication settings. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02002](/error-codes/API02002.md) — Token Expired * [API02007](/error-codes/API02007.md) — Token Refresh Failed --- # API02010: Auth Required ## What This Means[​](#what-this-means "Direct link to What This Means") The action you're trying to perform requires authentication, but you're not currently logged in. The POS needs valid credentials to access this resource. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Not logged in** — You haven't authenticated yet * **Session cleared** — Your session was cleared or expired * **Accessing protected resource** — The resource requires authentication * **App data cleared** — Stored credentials were removed ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ------------------------- | ------------------------------ | | `rest_login_required` | WordPress REST API | | `jwt_auth_no_auth_header` | JWT Authentication plugin | | HTTP 401 | Any server response (fallback) | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Log In[​](#1-log-in "Direct link to 1. Log In") If you haven't logged in: 1. Open the POS login screen 2. Enter your WordPress credentials 3. Complete the authentication process ### 2. Check Session Status[​](#2-check-session-status "Direct link to 2. Check Session Status") If you thought you were logged in: * Your session may have expired * Look for [API02002](/error-codes/API02002.md) (Token Expired) for more details * Log in again to restore access ### 3. Verify Server Configuration[​](#3-verify-server-configuration "Direct link to 3. Verify Server Configuration") Ensure the API endpoints are properly configured: * WooCommerce REST API should be enabled * WCPOS plugin should be active * Authentication endpoints should be accessible ### 4. Check for Browser/App Issues[​](#4-check-for-browserapp-issues "Direct link to 4. Check for Browser/App Issues") If you're being logged out unexpectedly: * Clear browser cache (if using web version) * Check that cookies/local storage aren't being blocked * Verify the app has permission to store data ## What Requires Authentication?[​](#what-requires-authentication "Direct link to What Requires Authentication?") Most POS operations require authentication: * Viewing products and customers * Creating and editing orders * Processing payments * Accessing reports Only the initial login screen is accessible without authentication. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API02001](/error-codes/API02001.md) — Invalid Credentials * [API02002](/error-codes/API02002.md) — Token Expired --- # API03001: Invalid Request Format ## What This Means[​](#what-this-means "Direct link to What This Means") The request sent to the server was not in the expected format. The server couldn't understand what the POS was asking for because the request structure was incorrect. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Corrupted data** — Data was corrupted before sending * **Software bug** — An issue in the POS application * **Proxy interference** — A proxy or firewall modified the request * **Character encoding issues** — Special characters weren't encoded properly ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ----------- | ------------------------------ | | HTTP 400 | Any server response (fallback) | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Retry the Action[​](#1-retry-the-action "Direct link to 1. Retry the Action") Sometimes this is a one-time glitch: * Wait a moment and try again * Refresh the POS and retry ### 2. Check for Special Characters[​](#2-check-for-special-characters "Direct link to 2. Check for Special Characters") If you're entering data with special characters: * Try removing emojis or unusual symbols * Use standard characters for product names, etc. ### 3. Update the POS[​](#3-update-the-pos "Direct link to 3. Update the POS") Ensure you're running the latest version: * Check for app updates * Update the WCPOS plugin on your server ### 4. Check Network Configuration[​](#4-check-network-configuration "Direct link to 4. Check Network Configuration") If you're behind a proxy: * Verify the proxy isn't modifying requests * Check firewall rules * Try accessing from a different network ### 5. Report the Issue[​](#5-report-the-issue "Direct link to 5. Report the Issue") If this happens consistently: * Note what action triggers the error * Check browser console for details (web version) * Report on [GitHub](https://github.com/wcpos) with reproduction steps ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API03002](/error-codes/API03002.md) — Missing Required Parameters * [API03003](/error-codes/API03003.md) — Invalid Parameter Value --- # API03002: Missing Required Parameters ## What This Means[​](#what-this-means "Direct link to What This Means") The request is missing data that the server needs to complete the action. Required fields were not included in the request. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Incomplete form** — Required fields weren't filled in * **Data not saved** — Form data wasn't captured properly * **Version mismatch** — Plugin expects different parameters than the POS sends * **Custom fields** — Required custom fields are missing ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Complete Required Fields[​](#1-complete-required-fields "Direct link to 1. Complete Required Fields") Check that all required information is filled in: * Customer details (if required) * Product information * Order details ### 2. Refresh and Retry[​](#2-refresh-and-retry "Direct link to 2. Refresh and Retry") The form state may be incomplete: 1. Refresh the POS 2. Re-enter the required information 3. Try the action again ### 3. Check Plugin Versions[​](#3-check-plugin-versions "Direct link to 3. Check Plugin Versions") Ensure compatibility: * Update the WCPOS plugin * Update the POS application * Both should be on compatible versions ### 4. Check Required Field Settings[​](#4-check-required-field-settings "Direct link to 4. Check Required Field Settings") In WooCommerce, some fields may be marked as required: * Review checkout field requirements * Check custom field configurations * Adjust requirements if needed ### 5. Check Custom Integrations[​](#5-check-custom-integrations "Direct link to 5. Check Custom Integrations") If using custom plugins or integrations: * They may require additional fields * Review plugin documentation * Check for conflicts ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API03001](/error-codes/API03001.md) — Invalid Request Format * [API03003](/error-codes/API03003.md) — Invalid Parameter Value --- # API03003: Invalid Parameter Value ## What This Means[​](#what-this-means "Direct link to What This Means") One of the values in your request is invalid. The data format, type, or value doesn't match what the server expects. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Wrong data type** — Text where a number is expected (or vice versa) * **Out of range** — Value exceeds allowed limits * **Invalid format** — Email, phone, or other formatted fields are incorrect * **Invalid reference** — Referencing an ID that doesn't exist ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ----------------------------- | -------------------- | | `rest_invalid_param` | WordPress REST API | | `woocommerce_rest_invalid_id` | WooCommerce REST API | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Input Values[​](#1-check-input-values "Direct link to 1. Check Input Values") Review the data you're submitting: * **Prices** — Should be valid numbers * **Quantities** — Should be positive integers * **Emails** — Must be valid email format * **IDs** — Must reference existing records ### 2. Look for Specific Field Errors[​](#2-look-for-specific-field-errors "Direct link to 2. Look for Specific Field Errors") The error may indicate which field is invalid: * Check the error message details * Correct the specific field * Retry the action ### 3. Verify Referenced Data Exists[​](#3-verify-referenced-data-exists "Direct link to 3. Verify Referenced Data Exists") If referencing products, customers, or other records: * Ensure the item exists in WooCommerce * Check if it was recently deleted * Sync data to refresh local records ### 4. Check Field Constraints[​](#4-check-field-constraints "Direct link to 4. Check Field Constraints") WooCommerce may have constraints: * Maximum/minimum values * Required formats * Allowed options for select fields ### 5. Clear and Re-enter[​](#5-clear-and-re-enter "Direct link to 5. Clear and Re-enter") Sometimes data gets corrupted: * Clear the problematic field * Re-enter the value from scratch * Avoid copy-pasting from other sources ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API03002](/error-codes/API03002.md) — Missing Required Parameters * [DB03002](/error-codes/DB03002.md) — Invalid Data Type --- # API03004: Request Too Large ## What This Means[​](#what-this-means "Direct link to What This Means") The request you're sending exceeds the server's size limits. This typically happens when trying to send too much data at once. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Large batch operations** — Trying to sync too many records at once * **Large images** — Uploading oversized images * **Too many items** — Order with extremely many line items * **Server limits** — PHP or web server has low upload limits ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Reduce Request Size[​](#1-reduce-request-size "Direct link to 1. Reduce Request Size") If syncing data: * Try syncing in smaller batches * The POS should handle this automatically * Wait for current sync to complete before starting another ### 2. Check Image Sizes[​](#2-check-image-sizes "Direct link to 2. Check Image Sizes") If uploading images: * Resize images before uploading * Use compressed formats (JPEG vs BMP) * Most product images work well under 1MB ### 3. Split Large Orders[​](#3-split-large-orders "Direct link to 3. Split Large Orders") If an order has many items: * Consider splitting into multiple orders * This is rare in normal POS usage ### 4. Increase Server Limits[​](#4-increase-server-limits "Direct link to 4. Increase Server Limits") Contact your hosting provider or edit PHP settings: ``` // In php.ini or .htaccess upload_max_filesize = 64M post_max_size = 64M max_input_vars = 5000 ``` ### 5. Check Web Server Limits[​](#5-check-web-server-limits "Direct link to 5. Check Web Server Limits") Nginx or Apache may have their own limits: * `client_max_body_size` for Nginx * `LimitRequestBody` for Apache ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API03005](/error-codes/API03005.md) — Rate Limit Exceeded * [API03007](/error-codes/API03007.md) — Request Queue Full --- # API03005: Rate Limit Exceeded ## What This Means[​](#what-this-means "Direct link to What This Means") You've made too many requests to the server in a short period. Rate limiting protects the server from being overwhelmed. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Rapid sync operations** — Multiple devices syncing simultaneously * **Aggressive refresh** — Refreshing data too frequently * **Security plugin** — A plugin is enforcing request limits * **Hosting limits** — Your hosting plan has API rate limits ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ----------- | ------------------------------ | | HTTP 429 | Any server response (fallback) | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Wait and Retry[​](#1-wait-and-retry "Direct link to 1. Wait and Retry") Rate limits are temporary: * Wait 1-5 minutes * The POS will automatically retry * Avoid manually refreshing repeatedly ### 2. Reduce Concurrent Operations[​](#2-reduce-concurrent-operations "Direct link to 2. Reduce Concurrent Operations") If using multiple POS terminals: * Stagger initial sync across devices * Avoid refreshing all devices at once * Let one complete before starting another ### 3. Check Security Plugins[​](#3-check-security-plugins "Direct link to 3. Check Security Plugins") Plugins like Wordfence may block rapid requests: * Whitelist the POS application * Whitelist your POS device IPs * Adjust rate limiting thresholds ### 4. Review Hosting Limits[​](#4-review-hosting-limits "Direct link to 4. Review Hosting Limits") Some hosts limit API requests: * Check your hosting plan details * Consider upgrading if limits are too low * Contact support about increasing limits ### 5. Optimise Sync Frequency[​](#5-optimise-sync-frequency "Direct link to 5. Optimise Sync Frequency") In POS settings: * Adjust auto-refresh intervals * Use manual sync when appropriate * Avoid unnecessary data refreshes ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API03004](/error-codes/API03004.md) — Request Too Large * [API03007](/error-codes/API03007.md) — Request Queue Full --- # API03006: Unsupported Method ## What This Means[​](#what-this-means "Direct link to What This Means") The HTTP method used (GET, POST, PUT, DELETE, etc.) is not supported for this endpoint. The server doesn't accept this type of request for this URL. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Version mismatch** — POS and plugin versions are incompatible * **Endpoint removed** — An API endpoint was deprecated * **Server configuration** — Web server blocking certain HTTP methods * **Plugin conflict** — Another plugin modifying REST API behaviour ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Update Both Components[​](#1-update-both-components "Direct link to 1. Update Both Components") Ensure compatibility: * Update the WCPOS WordPress plugin * Update the POS application * Check release notes for breaking changes ### 2. Check Server Configuration[​](#2-check-server-configuration "Direct link to 2. Check Server Configuration") Some servers block certain HTTP methods: * Ensure PUT and DELETE methods are allowed * Check `.htaccess` for method restrictions * Review Nginx configuration ### 3. Verify REST API Access[​](#3-verify-rest-api-access "Direct link to 3. Verify REST API Access") Test the WordPress REST API: 1. Visit `https://yoursite.com/wp-json/` in a browser 2. It should return JSON data 3. If not, the REST API may be disabled or blocked ### 4. Check for Plugin Conflicts[​](#4-check-for-plugin-conflicts "Direct link to 4. Check for Plugin Conflicts") Disable other plugins temporarily: * Security plugins may block methods * Other REST API plugins may cause conflicts * Re-enable one by one to find the issue ### 5. Review Hosting Restrictions[​](#5-review-hosting-restrictions "Direct link to 5. Review Hosting Restrictions") Some hosts restrict HTTP methods: * Contact hosting support * Request they enable all standard methods * Consider switching hosts if too restrictive ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API03001](/error-codes/API03001.md) — Invalid Request Format * [API05004](/error-codes/API05004.md) — WordPress API Disabled --- # API03007: Request Queue Full ## What This Means[​](#what-this-means "Direct link to What This Means") The POS has too many pending requests waiting to be sent. The internal queue is full and cannot accept more requests until some complete. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Slow network** — Requests backing up due to slow connection * **Server unresponsive** — Server taking too long to respond * **Rapid actions** — Performing many actions faster than they can process * **Sync overload** — Large sync operation blocking the queue ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Wait for Queue to Clear[​](#1-wait-for-queue-to-clear "Direct link to 1. Wait for Queue to Clear") Give pending requests time to complete: * Wait 30-60 seconds * Watch for sync indicators to complete * Avoid additional actions until cleared ### 2. Check Network Connection[​](#2-check-network-connection "Direct link to 2. Check Network Connection") A slow connection causes backup: * Test your internet speed * Try a faster connection * Move closer to WiFi router ### 3. Check Server Response Time[​](#3-check-server-response-time "Direct link to 3. Check Server Response Time") If the server is slow: * Test accessing your site in a browser * Contact hosting if site is slow * Wait for server load to decrease ### 4. Restart the POS[​](#4-restart-the-pos "Direct link to 4. Restart the POS") If the queue is stuck: 1. Close the POS application 2. Wait a moment 3. Reopen the POS 4. Pending requests may need to be re-initiated ### 5. Avoid Rapid Actions[​](#5-avoid-rapid-actions "Direct link to 5. Avoid Rapid Actions") During sync or slow periods: * Wait for one action to complete before starting another * Don't repeatedly click buttons * Be patient with network operations ## Offline Behaviour[​](#offline-behaviour "Direct link to Offline Behaviour") When the queue fills due to offline conditions: * The POS will hold pending requests until back online * You can still browse cached products and customers * You can start new orders and add items to the cart * Completing orders requires connectivity to be restored ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API03004](/error-codes/API03004.md) — Request Too Large * [API03005](/error-codes/API03005.md) — Rate Limit Exceeded --- # API04001: Invalid Response Format ## What This Means[​](#what-this-means "Direct link to What This Means") The server responded, but the response format is not what the POS expected. The server should return JSON data, but something else was received. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **PHP error displayed** — A PHP error is being output before JSON * **Plugin conflict** — Another plugin is outputting content * **Maintenance mode** — Site is showing a maintenance page * **Wrong content type** — Server sending HTML instead of JSON * **Caching issue** — A cached error page is being served ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Your Site[​](#1-check-your-site "Direct link to 1. Check Your Site") Visit your WordPress site in a browser: * Is it displaying normally? * Are there any visible errors? * Is it in maintenance mode? ### 2. Check for PHP Errors[​](#2-check-for-php-errors "Direct link to 2. Check for PHP Errors") In `wp-config.php`, temporarily enable debugging: ``` define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); ``` Check `wp-content/debug.log` for errors. ### 3. Test the REST API Directly[​](#3-test-the-rest-api-directly "Direct link to 3. Test the REST API Directly") Visit `https://yoursite.com/wp-json/` in your browser: * Should return JSON data * If you see HTML or errors, there's a problem * Check for plugin-related output ### 4. Disable Caching Temporarily[​](#4-disable-caching-temporarily "Direct link to 4. Disable Caching Temporarily") Caching plugins may serve stale responses: * Clear all caches * Temporarily disable caching plugins * Exclude the REST API from caching ### 5. Check for Plugin Conflicts[​](#5-check-for-plugin-conflicts "Direct link to 5. Check for Plugin Conflicts") If a plugin outputs content on every page: 1. Disable all non-essential plugins 2. Test the POS 3. Re-enable plugins one by one ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API04003](/error-codes/API04003.md) — Malformed JSON Response * [API05005](/error-codes/API05005.md) — Plugin Not Found --- # API04002: Unexpected Response Code ## What This Means[​](#what-this-means "Direct link to What This Means") The server returned an HTTP status code that wasn't expected for this request. Common codes include 500 (server error), 403 (forbidden), 404 (not found), etc. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **500 Internal Server Error** — PHP crashed or encountered an error * **403 Forbidden** — Access denied by security settings * **404 Not Found** — The endpoint doesn't exist * **502/503/504** — Server gateway or availability issues ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### For 500 Errors (Server Error)[​](#for-500-errors-server-error "Direct link to For 500 Errors (Server Error)") 1. Check PHP error logs 2. Increase PHP memory limit 3. Look for plugin conflicts 4. Check `wp-content/debug.log` ### For 403 Errors (Forbidden)[​](#for-403-errors-forbidden "Direct link to For 403 Errors (Forbidden)") 1. Check security plugin settings (Wordfence, Sucuri, etc.) 2. Whitelist the POS or your IP 3. Check `.htaccess` for blocking rules 4. Verify ModSecurity isn't blocking requests ### For 404 Errors (Not Found)[​](#for-404-errors-not-found "Direct link to For 404 Errors (Not Found)") 1. Verify the WCPOS plugin is active 2. Flush WordPress permalinks (Settings → Permalinks → Save) 3. Check if REST API is enabled 4. Verify URL configuration ### For 502/503/504 Errors (Gateway Issues)[​](#for-502503504-errors-gateway-issues "Direct link to For 502/503/504 Errors (Gateway Issues)") 1. Contact your hosting provider 2. Wait for server to recover 3. Check if site is under heavy load 4. Verify server is running ### General Troubleshooting[​](#general-troubleshooting "Direct link to General Troubleshooting") 1. Try accessing your site directly 2. Check hosting control panel for issues 3. Review server access logs 4. Contact hosting support if needed ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API04001](/error-codes/API04001.md) — Invalid Response Format * [API01008](/error-codes/API01008.md) — Website Unavailable --- # API04003: Malformed JSON Response ## What This Means[​](#what-this-means "Direct link to What This Means") The server returned data that appears to be JSON but is corrupted or invalid. The POS couldn't parse the response because the JSON syntax is broken. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **PHP notices/warnings** — PHP output before the JSON * **BOM (Byte Order Mark)** — Invisible characters at file start * **Encoding issues** — Character encoding problems * **Truncated response** — Response cut off mid-transmission * **Plugin output** — A plugin added non-JSON content ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check for PHP Notices[​](#1-check-for-php-notices "Direct link to 1. Check for PHP Notices") PHP notices/warnings before JSON break parsing: In `wp-config.php`: ``` define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); ``` Review `wp-content/debug.log` and fix any issues. ### 2. Check for BOM Characters[​](#2-check-for-bom-characters "Direct link to 2. Check for BOM Characters") Some text editors add invisible BOM characters: * Re-save PHP files without BOM * Use UTF-8 without BOM encoding * Check recently edited files ### 3. Verify Complete Response[​](#3-verify-complete-response "Direct link to 3. Verify Complete Response") If responses are being truncated: * Check PHP output buffering settings * Increase `output_buffering` in php.ini * Check for timeout issues ### 4. Test API Directly[​](#4-test-api-directly "Direct link to 4. Test API Directly") In your browser or using curl: ``` curl -v https://yoursite.com/wp-json/wcpos/v1/ ``` Look for any unexpected content before the JSON. ### 5. Check Character Encoding[​](#5-check-character-encoding "Direct link to 5. Check Character Encoding") Ensure database and PHP use UTF-8: * Check `wp-config.php` charset settings * Verify database tables are UTF-8 * Look for special characters causing issues ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API04001](/error-codes/API04001.md) — Invalid Response Format * [API04005](/error-codes/API04005.md) — JSON Recovery Attempted --- # API04004: Missing Response Data ## What This Means[​](#what-this-means "Direct link to What This Means") The server responded successfully, but the response is missing expected data. The JSON is valid but doesn't contain the information the POS needs. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Empty results** — No data matches the query * **Permission restrictions** — Data filtered due to permissions * **Plugin filtering** — Another plugin filtering API responses * **Version mismatch** — API version differences * **Database issues** — Data not present in WooCommerce ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify Data Exists[​](#1-verify-data-exists "Direct link to 1. Verify Data Exists") Check in WordPress Admin: * Are there products in WooCommerce? * Are there customers to load? * Does the specific item exist? ### 2. Check User Permissions[​](#2-check-user-permissions "Direct link to 2. Check User Permissions") Your user may not have access to all data: * Verify user role capabilities * Check POS access settings * Try with an administrator account ### 3. Check API Response Filters[​](#3-check-api-response-filters "Direct link to 3. Check API Response Filters") Some plugins filter REST API responses: * Disable filtering plugins temporarily * Check for custom API filters in your theme * Review security plugin settings ### 4. Update Both Components[​](#4-update-both-components "Direct link to 4. Update Both Components") Version mismatches can cause issues: * Update WCPOS plugin * Update the POS application * Check for compatibility notes ### 5. Check WooCommerce Data[​](#5-check-woocommerce-data "Direct link to 5. Check WooCommerce Data") In WooCommerce: * Verify products are published (not draft) * Check if items are marked as visible * Ensure data isn't corrupted ## Empty vs. Missing[​](#empty-vs-missing "Direct link to Empty vs. Missing") * **Empty response** — Valid response with no results (may be expected) * **Missing fields** — Response lacks required data fields (this error) ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API04001](/error-codes/API04001.md) — Invalid Response Format * [API02004](/error-codes/API02004.md) — User Not Authorized --- # API04005: JSON Recovery Attempted ## What This Means[​](#what-this-means "Direct link to What This Means") The server sent a response with some invalid JSON content, but the POS attempted to recover and extract valid data. This is an informational notice rather than a critical error. ## What Happened[​](#what-happened "Direct link to What Happened") The POS detected: 1. The response contained extra content before or after the JSON 2. The core JSON data was still identifiable 3. Recovery was attempted by extracting the valid JSON portion ## Common Causes[​](#common-causes "Direct link to Common Causes") * **PHP notices in output** — PHP warnings mixed with JSON * **Debug output** — Development debugging left enabled * **Plugin notices** — Other plugins outputting notices * **Whitespace issues** — Extra whitespace around JSON ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Disable PHP Display Errors[​](#1-disable-php-display-errors "Direct link to 1. Disable PHP Display Errors") In `wp-config.php`: ``` define('WP_DEBUG_DISPLAY', false); ini_set('display_errors', 0); ``` ### 2. Enable Error Logging Instead[​](#2-enable-error-logging-instead "Direct link to 2. Enable Error Logging Instead") Keep errors logged for debugging: ``` define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); ``` ### 3. Check for Plugin Debug Mode[​](#3-check-for-plugin-debug-mode "Direct link to 3. Check for Plugin Debug Mode") Some plugins have debug modes that output extra content: * Review plugin settings * Disable debug/development modes * Check for verbose logging options ### 4. Review Recent Changes[​](#4-review-recent-changes "Direct link to 4. Review Recent Changes") If this started recently: * What changed on your server? * Were plugins updated? * Were PHP settings modified? ## Is This Serious?[​](#is-this-serious "Direct link to Is This Serious?") While the POS recovered from this issue, it indicates a configuration problem that should be fixed. The recovery process: * May not always work * Adds processing overhead * Could mask other issues Fix the underlying cause to ensure reliable operation. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API04003](/error-codes/API04003.md) — Malformed JSON Response * [API04001](/error-codes/API04001.md) — Invalid Response Format --- # API04006: Resource Not Found ## What This Means[​](#what-this-means "Direct link to What This Means") The server could not find the requested resource. This typically corresponds to an HTTP 404 status code, indicating the product, order, customer, or other resource you're trying to access doesn't exist. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Record deleted** — The resource was deleted on the server * **Wrong ID** — An incorrect or outdated ID is being used * **Sync issues** — Local data references a resource that no longer exists * **URL misconfiguration** — The API endpoint is incorrect * **Permalink issues** — WordPress permalinks need to be refreshed ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | --------------- | ------------------- | | `rest_no_route` | WordPress REST API | | HTTP 404 | Any server response | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check if the Resource Exists[​](#1-check-if-the-resource-exists "Direct link to 1. Check if the Resource Exists") Verify the resource still exists on your WooCommerce site: * Log into WordPress admin * Navigate to the relevant section (Products, Orders, Customers) * Search for the item by ID or name ### 2. Refresh Local Data[​](#2-refresh-local-data "Direct link to 2. Refresh Local Data") If the resource was deleted server-side: 1. Open the POS settings 2. Navigate to the relevant data section 3. Trigger a sync/refresh to update local data 4. The deleted item should be removed locally ### 3. Check WordPress Permalinks[​](#3-check-wordpress-permalinks "Direct link to 3. Check WordPress Permalinks") If multiple resources are not found: 1. Go to **Settings → Permalinks** in WordPress admin 2. Click **Save Changes** (even without making changes) 3. This refreshes the permalink structure ### 4. Verify API Routes[​](#4-verify-api-routes "Direct link to 4. Verify API Routes") Test the REST API directly: ``` https://yoursite.com/wp-json/wc/v3/products ``` If this returns a 404, there may be a server configuration issue. ### 5. Check for Plugin Conflicts[​](#5-check-for-plugin-conflicts "Direct link to 5. Check for Plugin Conflicts") If REST API routes are missing: 1. Ensure WooCommerce is active 2. Ensure WCPOS plugin is active 3. Disable other plugins temporarily to test ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API04001](/error-codes/API04001.md) — Invalid Response Format * [API04002](/error-codes/API04002.md) — Unexpected Response Code * [API05002](/error-codes/API05002.md) — WCPOS Plugin Not Found --- # API05001: WooCommerce API Disabled ## What This Means[​](#what-this-means "Direct link to What This Means") The WooCommerce REST API is disabled on your site. WCPOS requires the REST API to communicate with WooCommerce and access store data. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **WooCommerce setting** — The REST API was intentionally disabled * **Security plugin** — A security plugin is blocking API access * **Hosting restriction** — Your host has disabled REST API access * **Permalink issues** — Permalinks not configured for REST API ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Enable WooCommerce REST API[​](#1-enable-woocommerce-rest-api "Direct link to 1. Enable WooCommerce REST API") In WordPress Admin: 1. Go to WooCommerce → Settings → Advanced → REST API 2. Ensure the REST API is enabled 3. Verify API keys are created ### 2. Check WordPress REST API[​](#2-check-wordpress-rest-api "Direct link to 2. Check WordPress REST API") The WooCommerce API depends on WordPress REST API: 1. Visit `https://yoursite.com/wp-json/` in your browser 2. Should return JSON data 3. If not, see [API05004](/error-codes/API05004.md) ### 3. Check Security Plugins[​](#3-check-security-plugins "Direct link to 3. Check Security Plugins") Common security plugins that may block the API: * **Wordfence** — Check firewall settings * **iThemes Security** — Check REST API settings * **All In One WP Security** — Review firewall rules Whitelist REST API endpoints or the POS application. ### 4. Check .htaccess[​](#4-check-htaccess "Direct link to 4. Check .htaccess") Look for rules blocking API access: ``` # Remove or modify rules blocking /wp-json/ # Ensure mod_rewrite is enabled ``` ### 5. Flush Permalinks[​](#5-flush-permalinks "Direct link to 5. Flush Permalinks") Sometimes permalink settings need refreshing: 1. Go to Settings → Permalinks 2. Click "Save Changes" (even without making changes) 3. This regenerates rewrite rules ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API05004](/error-codes/API05004.md) — WordPress API Disabled * [API02006](/error-codes/API02006.md) — API Key Invalid --- # API05002: WCPOS Plugin Not Found ## What This Means[​](#what-this-means "Direct link to What This Means") The WCPOS plugin is not installed or not active on your WordPress site. The POS application requires this plugin to communicate with WooCommerce. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Plugin not installed** — The plugin was never installed * **Plugin deactivated** — The plugin was disabled * **Plugin deleted** — The plugin files were removed * **Wrong site** — Connected to a site without WCPOS ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Install the Plugin[​](#1-install-the-plugin "Direct link to 1. Install the Plugin") If not installed: 1. Go to WordPress Admin → Plugins → Add New 2. Search for "WCPOS" 3. Install and activate the plugin Or download from [WordPress.org](https://wordpress.org/plugins/woocommerce-pos/) ### 2. Activate the Plugin[​](#2-activate-the-plugin "Direct link to 2. Activate the Plugin") If installed but not active: 1. Go to Plugins → Installed Plugins 2. Find "WCPOS" 3. Click "Activate" ### 3. Check for Errors[​](#3-check-for-errors "Direct link to 3. Check for Errors") If the plugin won't activate: * Check for PHP errors in your error log * Verify WooCommerce is installed and active * Check PHP version requirements * Look for plugin conflicts ### 4. Verify the URL[​](#4-verify-the-url "Direct link to 4. Verify the URL") Ensure the POS is configured to connect to the correct WordPress site: * Check the URL in POS settings * Verify it matches your WordPress installation ### 5. Reinstall if Necessary[​](#5-reinstall-if-necessary "Direct link to 5. Reinstall if Necessary") If the plugin is corrupted: 1. Deactivate and delete the plugin 2. Reinstall from WordPress.org 3. Activate the plugin ## Requirements[​](#requirements "Direct link to Requirements") WordPress : Recent version WooCommerce : Recent version PHP : Version 7.4 or higher ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API05003](/error-codes/API05003.md) — WCPOS Plugin Outdated * [API05005](/error-codes/API05005.md) — Plugin Not Found --- # API05003: WCPOS Plugin Outdated ## What This Means[​](#what-this-means "Direct link to What This Means") The WCPOS plugin installed on your server is outdated and not compatible with your version of the POS application. You need to update the plugin. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Plugin not updated** — Auto-updates may be disabled * **Update failed** — A previous update attempt failed * **Version mismatch** — POS app updated but plugin wasn't * **Staging/dev site** — Testing on an older version ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Update the Plugin[​](#1-update-the-plugin "Direct link to 1. Update the Plugin") In WordPress Admin: 1. Go to Plugins → Installed Plugins 2. Find "WCPOS" 3. If an update is available, click "Update Now" ### 2. Enable Auto-Updates[​](#2-enable-auto-updates "Direct link to 2. Enable Auto-Updates") To prevent future mismatches: 1. Go to Plugins → Installed Plugins 2. Find "WCPOS" 3. Click "Enable auto-updates" ### 3. Manual Update[​](#3-manual-update "Direct link to 3. Manual Update") If automatic update fails: 1. Download the latest version from [WordPress.org](https://wordpress.org/plugins/woocommerce-pos/) 2. Deactivate the current plugin 3. Delete the old plugin files 4. Upload and activate the new version ### 4. Check for Update Errors[​](#4-check-for-update-errors "Direct link to 4. Check for Update Errors") If updates are failing: * Check file permissions on wp-content/plugins * Verify you have disk space * Look for PHP memory issues * Check error logs for details ### 5. Downgrade POS App (Temporary)[​](#5-downgrade-pos-app-temporary "Direct link to 5. Downgrade POS App (Temporary)") If you can't update the plugin immediately: * Use an older version of the POS app * This is a temporary workaround only * Plan to update the plugin soon ## Version Compatibility[​](#version-compatibility "Direct link to Version Compatibility") Always keep both components updated: * The POS application * The WCPOS WordPress plugin Check release notes for any breaking changes when updating. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API05002](/error-codes/API05002.md) — WCPOS Plugin Not Found * [API05005](/error-codes/API05005.md) — Plugin Not Found --- # API05004: WordPress API Disabled ## What This Means[​](#what-this-means "Direct link to What This Means") The WordPress REST API is disabled on your site. All modern WordPress functionality, including WooCommerce and WCPOS, depends on this API. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Security plugin** — A plugin is blocking REST API access * **Hosting restriction** — Your host disabled the REST API * **Custom code** — A theme or plugin disabled the API * **Firewall rules** — WAF blocking REST API endpoints ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Test the REST API[​](#1-test-the-rest-api "Direct link to 1. Test the REST API") Visit `https://yoursite.com/wp-json/` in your browser: * Should return JSON with available routes * If you get an error or nothing, it's blocked ### 2. Check Security Plugins[​](#2-check-security-plugins "Direct link to 2. Check Security Plugins") Common plugins that block REST API: **Wordfence:** * Firewall → All Firewall Options * Disable "Disable REST API" option **iThemes Security:** * Security → Settings → WordPress Tweaks * Enable REST API **Disable REST API Plugin:** * Deactivate this plugin entirely ### 3. Check for Custom Code[​](#3-check-for-custom-code "Direct link to 3. Check for Custom Code") Look in your theme's `functions.php` or custom plugins for: ``` // This code disables REST API - remove it add_filter('rest_authentication_errors', function($result) { return new WP_Error('rest_disabled', 'REST API disabled'); }); ``` ### 4. Check .htaccess[​](#4-check-htaccess "Direct link to 4. Check .htaccess") Remove any rules blocking `/wp-json/`: ``` # Bad - blocks REST API RewriteRule ^wp-json - [F,L] ``` ### 5. Contact Hosting Provider[​](#5-contact-hosting-provider "Direct link to 5. Contact Hosting Provider") Some hosts block REST API by default: * Request they enable it * Ask about any security restrictions * Check hosting documentation ## Why REST API Matters[​](#why-rest-api-matters "Direct link to Why REST API Matters") The WordPress REST API is essential for: * Mobile apps * Third-party integrations * WooCommerce functions * WCPOS operation Disabling it breaks many features. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API05001](/error-codes/API05001.md) — WooCommerce API Disabled * [API03006](/error-codes/API03006.md) — Unsupported Method --- # API05005: Plugin Not Found ## What This Means[​](#what-this-means "Direct link to What This Means") A required WordPress plugin is not installed or active. This could be WooCommerce itself, a required extension, or an integration plugin. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **WooCommerce deactivated** — WooCommerce was disabled * **Required extension missing** — A needed WooCommerce extension isn't installed * **Plugin conflict** — Another plugin caused a required plugin to deactivate * **Failed update** — A plugin update failed and left it deactivated ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify WooCommerce is Active[​](#1-verify-woocommerce-is-active "Direct link to 1. Verify WooCommerce is Active") WCPOS requires WooCommerce: 1. Go to Plugins → Installed Plugins 2. Find "WooCommerce" 3. Ensure it's activated ### 2. Check for Required Extensions[​](#2-check-for-required-extensions "Direct link to 2. Check for Required Extensions") Some WCPOS features may require extensions: * Check error message for specific plugin name * Install and activate the required extension ### 3. Review Plugin Conflicts[​](#3-review-plugin-conflicts "Direct link to 3. Review Plugin Conflicts") If plugins were deactivated due to conflicts: 1. Check your email for WordPress notifications 2. Review error logs 3. Resolve conflicts and reactivate ### 4. Check Plugin Files[​](#4-check-plugin-files "Direct link to 4. Check Plugin Files") If a plugin's files are missing: 1. Reinstall the plugin from WordPress.org 2. Or restore from backup 3. Activate the plugin ### 5. Update All Plugins[​](#5-update-all-plugins "Direct link to 5. Update All Plugins") Outdated plugins may cause issues: 1. Go to Dashboard → Updates 2. Update all plugins 3. Verify all required plugins are active ## Required Plugins[​](#required-plugins "Direct link to Required Plugins") At minimum, WCPOS requires: * **WooCommerce** — The e-commerce platform * **WCPOS** — The POS plugin Additional features may require other plugins. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API05002](/error-codes/API05002.md) — WCPOS Plugin Not Found * [API05001](/error-codes/API05001.md) — WooCommerce API Disabled --- # API06001: Invalid URL Format ## What This Means[​](#what-this-means "Direct link to What This Means") The URL configured for your WooCommerce site is not in a valid format. URLs must follow standard web address conventions. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Missing protocol** — URL doesn't start with `http://` or `https://` * **Typo in URL** — Spelling errors in the domain * **Invalid characters** — Special characters that aren't allowed in URLs * **Incomplete URL** — URL is missing parts like the domain extension ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check URL Format[​](#1-check-url-format "Direct link to 1. Check URL Format") A valid URL should look like: * ✅ `https://yourstore.com` * ✅ `https://www.yourstore.com` * ✅ `https://store.yourdomain.com` * ❌ `yourstore.com` (missing protocol) * ❌ `https://yourstore` (missing extension) * ❌ `https://your store.com` (contains space) ### 2. Include the Protocol[​](#2-include-the-protocol "Direct link to 2. Include the Protocol") Always include `https://` or `http://`: * Preferred: `https://` (secure) * Fallback: `http://` (if HTTPS isn't available) ### 3. Remove Extra Characters[​](#3-remove-extra-characters "Direct link to 3. Remove Extra Characters") Ensure the URL doesn't have: * Trailing slashes (optional but be consistent) * Extra spaces * Special characters * URL parameters (unless required) ### 4. Verify the URL Works[​](#4-verify-the-url-works "Direct link to 4. Verify the URL Works") Test the URL in a browser: 1. Copy the URL you're using 2. Paste it in a browser 3. It should load your WordPress site ### 5. Update POS Configuration[​](#5-update-pos-configuration "Direct link to 5. Update POS Configuration") Enter the corrected URL in the POS settings: * Match exactly what works in your browser * Include or exclude `www.` as your site uses ## Examples[​](#examples "Direct link to Examples") | Invalid | Valid | | ---------------------- | --------------------- | | `mystore.com` | `https://mystore.com` | | `https://my store.com` | `https://mystore.com` | | `https://mystore` | `https://mystore.com` | | `htp://mystore.com` | `https://mystore.com` | ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API06002](/error-codes/API06002.md) — Missing API URL * [API01004](/error-codes/API01004.md) — DNS Resolution Failed --- # API06002: Missing API URL ## What This Means[​](#what-this-means "Direct link to What This Means") No URL has been configured for connecting to your WooCommerce store. The POS needs to know where your store is located. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **First-time setup** — URL was never entered * **Configuration cleared** — Settings were reset or cleared * **App data cleared** — Application data was deleted * **Migration issue** — URL lost during update or migration ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Enter Your Store URL[​](#1-enter-your-store-url "Direct link to 1. Enter Your Store URL") In the POS app: 1. Open settings or login screen 2. Find the URL/Site configuration field 3. Enter your WordPress site URL 4. Example: `https://yourstore.com` ### 2. Find Your WordPress URL[​](#2-find-your-wordpress-url "Direct link to 2. Find Your WordPress URL") If you're unsure of your URL: 1. Log into WordPress Admin 2. Go to Settings → General 3. Look at "WordPress Address (URL)" 4. Use this URL in the POS ### 3. Check Stored Settings[​](#3-check-stored-settings "Direct link to 3. Check Stored Settings") If the URL was previously configured: * Check if app data was accidentally cleared * Look for settings backup/export options * Re-enter the URL if needed ### 4. Verify URL is Correct[​](#4-verify-url-is-correct "Direct link to 4. Verify URL is Correct") Before saving: 1. Test the URL in a browser 2. Ensure it loads your WordPress site 3. Include `https://` or `http://` ## Setup Checklist[​](#setup-checklist "Direct link to Setup Checklist") When configuring WCPOS for the first time: 1. ☐ Enter your WordPress site URL 2. ☐ Verify WCPOS plugin is installed and active 3. ☐ Login with your WordPress credentials 4. ☐ Allow initial data sync to complete ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API06001](/error-codes/API06001.md) — Invalid URL Format * [API06003](/error-codes/API06003.md) — Invalid Site Configuration --- # API06003: Invalid Site Configuration ## What This Means[​](#what-this-means "Direct link to What This Means") The site configuration is invalid or incomplete. This could involve incorrect URLs, authentication settings, or other configuration issues. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Partial configuration** — Some settings are missing * **Mismatched settings** — Configuration doesn't match the site * **Corrupted configuration** — Settings were corrupted * **Site changes** — The site was modified without updating POS config ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Review All Settings[​](#1-review-all-settings "Direct link to 1. Review All Settings") Check the complete configuration: * Site URL is correct * Authentication is properly configured * Any additional settings are correct ### 2. Reconfigure from Scratch[​](#2-reconfigure-from-scratch "Direct link to 2. Reconfigure from Scratch") If configuration is corrupted: 1. Clear all stored settings 2. Start the setup process again 3. Enter fresh configuration ### 3. Check Site Requirements[​](#3-check-site-requirements "Direct link to 3. Check Site Requirements") Verify your WordPress site meets requirements: * WordPress is installed and accessible * WooCommerce is installed and active * WCPOS plugin is installed and active * Permalinks are enabled (not "Plain") ### 4. Test Site Access[​](#4-test-site-access "Direct link to 4. Test Site Access") Verify these URLs work in a browser: * `https://yoursite.com/` — Main site * `https://yoursite.com/wp-json/` — REST API * `https://yoursite.com/wp-json/wcpos/v1/` — WCPOS API ### 5. Check WordPress Settings[​](#5-check-wordpress-settings "Direct link to 5. Check WordPress Settings") In WordPress Admin: 1. Settings → General — Verify URLs 2. Settings → Permalinks — Ensure not "Plain" 3. WooCommerce → Status — Check for issues ## Configuration Requirements[​](#configuration-requirements "Direct link to Configuration Requirements") A valid configuration needs: * **Site URL** — Full URL with protocol * **Authentication** — Valid credentials or API keys * **Permissions** — User has POS access * **Plugins** — Required plugins are active ## Related Errors[​](#related-errors "Direct link to Related Errors") * [API06001](/error-codes/API06001.md) — Invalid URL Format * [API06002](/error-codes/API06002.md) — Missing API URL * [API05002](/error-codes/API05002.md) — WCPOS Plugin Not Found --- # AUTH101: Session expired ## What this means[​](#what-this-means "Direct link to What this means") Your session ended and you need to sign in again. Sign in again and repeat the request; no local data was lost. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Sign in again when prompted, then repeat the action — nothing on the till was lost. 2. Frequent expiries (several per day) usually come from the site: a security plugin shortening session lifetimes or clearing tokens. Ask the site administrator which security plugins run on the store. ## Details[​](#details "Direct link to Details") * Code `AUTH101` (`SESSION_EXPIRED`) * Severity warn * Introduced in WCPOS 1.10.0 --- # AUTH111: Credentials rejected ## What this means[​](#what-this-means "Direct link to What this means") The store did not accept the sign-in credentials. Re-enter the username and password, or reset the password in WordPress if it keeps failing. No order data is affected. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till** — for the cashier: re-enter the username and password; the store refused this pair. **On the store** — for the site administrator: 1. Confirm the account works by signing in to WP Admin with the same credentials; reset the password there if it fails. 2. If the credentials work in WP Admin but not in the POS, a login-protection or security plugin may be blocking programmatic sign-in — check its settings. ## Details[​](#details "Direct link to Details") * Code `AUTH111` (`CREDENTIALS_REJECTED`) * Severity warn * Introduced in WCPOS 1.10.0 --- # AUTH121: Signed in as wrong user ## What this means[​](#what-this-means "Direct link to What this means") The signed-in store account does not match the cashier on this till. Each cashier keeps their own till data, so working under another account can misfile orders. Sign out, then sign in with the cashier's own account. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. The POS signs the session out on its own to protect each cashier's data — no order data is mixed between accounts. 2. Sign back in with the cashier's own account; working under another account can misfile orders. 3. If tills are shared between cashiers, make switching accounts part of the handover routine. ## Details[​](#details "Direct link to Details") * Code `AUTH121` (`SIGNED_IN_AS_WRONG_USER`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH201: Insufficient role ## What this means[​](#what-this-means "Direct link to What this means") Your account does not have permission to perform this action. Ask a store administrator to check the account's roles and capabilities, then try again. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask your store administrator. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till** — for the cashier: note which action was refused (the log entry records it) and pass that to your administrator. **On the store** — for the site administrator: review the account's roles — POS cashiers need the POS capabilities WCPOS registers, and role-editing plugins can strip them. If the account can sign in but every product, customer or order request is refused, check whether it holds **more than one role**. Role-editor plugins such as Members apply a *Deny* placed on any one role to the whole account, so an Administrator who is also a Customer loses whatever the Customer role denies. Remove the extra role or clear the *Deny* marks; see [A user with more than one role](/settings/wp-admin/access.md#more-than-one-role). **Back at the till:** once the role is corrected, sign out and back in if a POS session is still open; otherwise, sign in again. Then retry the refused action. ## Details[​](#details "Direct link to Details") * Code `AUTH201` (`INSUFFICIENT_ROLE`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH301: Auth plugin conflict ## What this means[​](#what-this-means "Direct link to What this means") Another authentication plugin is preventing WCPOS from connecting. Ask the site administrator to resolve the named plugin conflict before signing in again. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **On the store** — for the site administrator: 1. The error names the conflicting plugin. Review that plugin's settings — most authentication plugins can exempt the WCPOS REST routes instead of being disabled outright. 2. If it is unclear which plugin conflicts, test on a staging copy by disabling security and login plugins one at a time. **At the till** — for the cashier: after the change, sign in again. ## Details[​](#details "Direct link to Details") * Code `AUTH301` (`AUTH_PLUGIN_CONFLICT`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH311: Rest route missing ## What this means[​](#what-this-means "Direct link to What this means") The WCPOS store route is unavailable. Ask the site administrator to check whether a security or proxy plugin is stripping WCPOS request headers. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till** — for the cashier: test both supported REST forms in a browser — your store's `/wp-json/` address and `/index.php?rest_route=/`. Only diagnose a REST block if neither returns JSON; then report that to your administrator. **On the store** — for the site administrator: 1. Confirm WCPOS is active: WP Admin → Plugins. 2. If neither REST form works, check whether a security plugin, proxy or CDN is stripping WCPOS request headers or blocking REST requests — firewall rules and disable-REST-API hardening options are the usual culprits. 3. On some hosts, re-saving permalinks (Settings → Permalinks → Save) restores missing REST routes. ## Details[​](#details "Direct link to Details") * Code `AUTH311` (`REST_ROUTE_MISSING`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH321: WooCommerce missing ## What this means[​](#what-this-means "Direct link to What this means") WooCommerce is not active on this site, so WCPOS cannot connect. WCPOS requires the WooCommerce plugin. Ask the site administrator to install or reactivate WooCommerce, then connect again. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Ask the site administrator to check WP Admin → Plugins: WooCommerce must be installed and active for WCPOS to connect. 2. If WooCommerce was deactivated by a failed update, reactivate it and watch for an error banner — WooCommerce → Status → Logs records why it failed. 3. Once WooCommerce is active again, reconnect from the till. ## Details[​](#details "Direct link to Details") * Code `AUTH321` (`WOOCOMMERCE_MISSING`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH331: WCPOS plugin outdated ## What this means[​](#what-this-means "Direct link to What this means") This store's WCPOS plugin is too old for this version of the app. The app has been updated but the WCPOS plugin on the store has not, and the two versions no longer work together. Ask whoever manages the site to update the WCPOS plugin in WP Admin, then connect again. Nothing needs to change on the till. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **On the store** — for whoever manages the WordPress site: 1. WP Admin → Plugins → update WCPOS to the latest version. If WCPOS Pro is installed, update it to a matching version at the same time. 2. If no update is offered, check WP Admin → Dashboard → Updates; for Pro, an unauthorized updater blocks updates (see [LICENSE301](/error-codes/LICENSE301.md)) — fix that first. **At the till** — for the cashier: once the store has been updated, reconnect. You do not need to type the store address again. **If the store can't be updated yet:** contact support instead — the till needs an app version that matches the plugin, and support can tell you which one. They'll ask for the app version (from the till) and the store's current WCPOS version (from WP Admin). ## Details[​](#details "Direct link to Details") * Code `AUTH331` (`WCPOS_PLUGIN_OUTDATED`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH401: TLS untrusted ## What this means[​](#what-this-means "Direct link to What this means") A secure connection to this store could not be trusted. Use the correct store address and ask the site administrator to repair the certificate before reconnecting. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Open the store address in a browser on the same device — the browser's padlock or warning page shows exactly what is wrong with the certificate (expired, self-signed, or issued for a different domain). 2. Check the address the POS uses: https\:// and the exact domain the certificate covers — with or without www matters. 3. Ask the site administrator or host to renew or fix the certificate; an automatic renewal silently failing is the most common cause. 4. Do not work around a certificate warning by disabling security — fix the certificate. ## Details[​](#details "Direct link to Details") * Code `AUTH401` (`TLS_UNTRUSTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH411: Store URL invalid ## What this means[​](#what-this-means "Direct link to What this means") The store address is missing or not a valid URL. Check the address for typos and include the full https\:// URL of the store's WordPress site, then try again. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Check the address for typos and enter the full URL including https\:// — for example . 2. Use the site's WordPress address, not an admin page or a checkout URL. 3. If the site lives in a subdirectory (for example /shop), include it. ## Details[​](#details "Direct link to Details") * Code `AUTH411` (`STORE_URL_INVALID`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH421: Auth token blocked by host ## What this means[​](#what-this-means "Direct link to What this means") The store's server is blocking the login token on every channel this app can use. The app confirmed the store is reachable, but the server (or a firewall, proxy, or security plugin in front of it) strips the Authorization header and also blocks the token when it is sent as a URL parameter. There is no third way to deliver a login token, so this must be fixed on the server. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **For your host / server** — the login token has no delivery channel until the server passes it through: 1. Allow the Authorization header through to WordPress — on Apache this is usually one line: `SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1`. 2. If the site uses `.htaccess` rewrites, keep WordPress's generated RewriteRule line that passes `HTTP_AUTHORIZATION` — security plugins sometimes remove it. 3. Behind a proxy or CDN, check its header allow-list: the Authorization request header must be forwarded to the origin. 4. If a web application firewall (WAF) is filtering URL parameters, allow the authorization parameter on `/wcpos/` REST routes. ## Details[​](#details "Direct link to Details") * Code `AUTH421` (`AUTH_TOKEN_BLOCKED_BY_HOST`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH431: Rest transport blocked ## What this means[​](#what-this-means "Direct link to What this means") The store's REST API did not answer on any address form this app can use. The app tried the store's REST API at its normal address (/wp-json/...) and at WordPress's built-in fallback address (/?rest\_route=...), and neither answered. The store's website itself may be up — this is specifically the REST API being unreachable, usually a security plugin hiding it or a firewall rule blocking it. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **On the store** — for the site administrator: if a security plugin hides or renames `/wp-json/` (for example WP Hide), allow WordPress's built-in `/?rest_route=` form as well — the app falls back to it automatically. **On the host / server:** 1. Check firewall (WAF) rules for anything matching `wp-json` or `rest_route` and allow the store's own REST API through. 2. If the server is behind a maintenance page or bot challenge, REST requests may be answered with an HTML page — disable the challenge for the REST API. **To test (anyone):** `https://your-store.com/?rest_route=/` should return JSON, not a 403 page or the site's homepage. ## Details[​](#details "Direct link to Details") * Code `AUTH431` (`REST_TRANSPORT_BLOCKED`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH441: Auth token too large ## What this means[​](#what-this-means "Direct link to What this means") The login token is larger than this server accepts. The server rejected the login token for size: a 400 when it travels in the Authorization header, or a 414 when it travels in the URL. No client-side encoding can shrink it — the server's header/URL size limits must be raised, or the token made smaller. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. On Apache, raise LimitRequestFieldSize (header path) or LimitRequestLine (URL path) in the vhost config. 2. On nginx, raise large\_client\_header\_buffers. 3. Behind a proxy or CDN, the limit may be at that layer — check both. 4. If limits cannot change, contact support about issuing a smaller token for this site. ## Details[​](#details "Direct link to Details") * Code `AUTH441` (`AUTH_TOKEN_TOO_LARGE`) * Severity error * Introduced in WCPOS 1.10.0 --- # AUTH999: Auth unexpected ## What this means[​](#what-this-means "Direct link to What this means") Signing in or staying signed in hit an unexpected problem. Try the action once more. If it repeats, sign out and back in, then use **Copy debug info** and contact support. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, use **Copy debug info** and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Try the action once more; if it fails again, sign out and back in. 2. Expand the log entry and note the event code and any serverCode — a 999 code means the cause has no dedicated code yet, and that context is what identifies it. 3. If it recurs, use Copy debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `AUTH999` (`AUTH_UNEXPECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # CHECKOUT101: Checkout failed cart safe ## What this means[​](#what-this-means "Direct link to What this means") Checkout did not finish, and the cart is still safe to retry. Review the cart and retry checkout; the current cart contents have been preserved. ## Your data[​](#your-data "Direct link to Your data") The order itself is safe and unchanged. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till** — for the cashier: 1. Review the cart — it is unchanged — and try checkout again. 2. If it fails again, expand the log entry in Store health → Logs — the serverCode and status say whether the store refused the order and why. 3. If the reason names a specific line item, remove it, complete the sale, and investigate that product afterwards. **On the store** — for the site administrator: a repeated failure with a 500-class status is a site problem — check WooCommerce → Status → Logs for a PHP error at the failure time. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT101` (`CHECKOUT_FAILED_CART_SAFE`) * Severity error * Introduced in WCPOS 1.10.0 --- # CHECKOUT111: Cart update failed ## What this means[​](#what-this-means "Direct link to What this means") This change could not be applied to the cart, which is unchanged. The item, fee, shipping line, or coupon was not added and nothing was removed. Try the action again. ## Your data[​](#your-data "Direct link to Your data") The order itself is safe and unchanged. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Try adding the item, fee, shipping line or coupon again — the cart itself is unchanged. 2. If the same item keeps failing, try a different product once: one failing item points at that record, everything failing points at the device. 3. If it keeps failing, restart WCPOS; export debug info and contact support if it continues. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT111` (`CART_UPDATE_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # CHECKOUT201: Checkout outcome unknown ## What this means[​](#what-this-means "Direct link to What this means") WCPOS could not confirm whether checkout completed. Do not retry blindly. Check the store for the order first, then export diagnostics if its outcome is still unclear. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — verify before retrying. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **First, don't make it worse:** do not retry checkout and do not charge the customer again until you know whether the order exists. **Check whether the order exists** — how depends on what you can reach: on WCPOS Pro, sync the POS and look in the till's Orders list; otherwise have someone open WooCommerce → Orders in WP Admin and search by the total and the last few minutes. If the order is there, the sale went through — do not create it again. **Then:** if no order exists after checking, retry checkout once. If it is still unclear, export debug info and contact support before another attempt. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT201` (`CHECKOUT_OUTCOME_UNKNOWN`) * Severity error * Introduced in WCPOS 1.10.0 --- # CHECKOUT211: Checkout empty response ## What this means[​](#what-this-means "Direct link to What this means") The store returned no checkout result, so the order status is unknown. Check whether the order was created before trying checkout again. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — verify before retrying. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **Check whether the order exists first** — an empty response often means the order was created but the confirmation never arrived. On WCPOS Pro, sync the POS and look in the till's Orders list; otherwise have someone check WooCommerce → Orders in WP Admin. Only retry checkout once you have confirmed no order was created. **On the store** — for the site administrator: 1. Check WooCommerce → Status → Logs for a fatal error during checkout — a PHP crash after the order is created produces exactly this. 2. If WooCommerce's log shows nothing, ask the hosting provider for the server's PHP error log — some fatal errors are captured only there. **For a developer:** in the browser's developer tools — or the desktop app's **Advanced → Toggle Developer Tools** — the checkout request on the Network tab with a success status but an empty or truncated body points at a plugin or server buffer cutting the response short. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT211` (`CHECKOUT_EMPTY_RESPONSE`) * Severity error * Introduced in WCPOS 1.10.0 --- # CHECKOUT301: SKU duplicate ## What this means[​](#what-this-means "Direct link to What this means") Checkout cannot continue because a product SKU is duplicated or invalid. Change or remove the named SKU, then retry with the preserved cart. ## Your data[​](#your-data "Direct link to Your data") The order itself is safe and unchanged. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. The log entry names the SKU the store refused. **At the till:** this product can't be sold until its SKU is fixed — remove the line from the cart, set the item aside, and complete the rest of the sale now. Come back to it once the store is corrected. **On the store** — for the site administrator: 1. In WP Admin, search Products for that SKU. If two products (or a product and a variation) share it, give each a unique SKU. If only one product has it, the SKU itself is malformed — correct it on that product. 2. Once the SKU is unique and valid, the till can add the item and complete the sale (the cart is preserved). ## Details[​](#details "Direct link to Details") * Code `CHECKOUT301` (`SKU_DUPLICATE`) * Severity error * Introduced in WCPOS 1.10.0 --- # CHECKOUT401: Totals diverged ## What this means[​](#what-this-means "Direct link to What this means") Your store calculated different totals for this order than the till showed. Check the order in your store admin before taking any further payment — the store's totals are the source of truth. If the difference is unexpected, export diagnostics and contact support. ## Your data[​](#your-data "Direct link to Your data") Money may have moved — verify the payment before acting. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till** — do this before the customer leaves: 1. Stop — take no further payment. The store's totals are the source of truth. 2. Confirm whether the customer paid and how much — on a card terminal, check its screen or receipt; for cash, the amount tendered; for another gateway, its own record. 3. If money was taken and the store's total differs, settle the difference (refund or additional charge) through your normal process before the customer leaves. **On the store** — for the site administrator: 1. Open the order in WP Admin and compare its totals with what the till showed; the log entry records which amounts diverged. 2. The usual causes are tax settings that differ from what the till expected, or a discount or pricing plugin recalculating on the server — review the store's tax settings first. 3. If the divergence is unexplained, export debug info and contact support with the order number. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT401` (`TOTALS_DIVERGED`) * Severity error * Introduced in WCPOS 1.10.0 --- # CHECKOUT411: Cart line price basis unreadable ## What this means[​](#what-this-means "Direct link to What this means") A line on this order has price details the POS could not read, so its amount was taken from the stored totals instead. Every line WCPOS adds to an order carries a small record of how its price was worked out — the price itself, whether tax was included, and its tax status. When that record cannot be read, WCPOS falls back to whatever totals were already saved on the line rather than recalculating it. The amount shown is usually still right, but nothing has confirmed it, so check the order total before taking payment. The usual cause is a line that was added by a much older version of WCPOS, or restored from a backup, in a format the current version no longer recognises. ## Your data[​](#your-data "Direct link to Your data") The order is safe and nothing has been lost. Only the affected line's amount is in question. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till** — do this before taking payment: 1. Check the order total against what you expect. The affected line's amount came from stored totals, not from a recalculated price. 2. Remove the affected line and add the product, fee or shipping method again. A freshly added line always carries readable price details, and the notice clears on the next order. 3. If the total was wrong, the re-added line corrects it — compare before and after. **On the store** — for the site administrator: 1. If this appears on lines added recently, rather than on old or restored orders, something is writing the POS price data in a format the app cannot read. 2. Note any plugin that modifies cart or order line data. Then open the log entry in **Store health → Logs**, use **Copy** (or **Share**) to send its details, and contact support with the order number. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT411` (`CART_LINE_PRICE_BASIS_UNREADABLE`) * Severity warn * Introduced in WCPOS 1.10.0 --- # CHECKOUT421: Order tax rate unknown ## What this means[​](#what-this-means "Direct link to What this means") This order refers to a tax rate your store no longer has, so its tax may be wrong. A line on the order carries a tax rate that is not in the store's current tax tables — almost always because that rate was deleted or edited in WooCommerce after the order was started. WCPOS cannot look the rate up, so the tax on this order may not match what the store would charge now. ## Your data[​](#your-data "Direct link to Your data") The order is safe. Only its tax amount is in question — check it before taking payment, and ask your store administrator about the tax rates. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till** — do this before taking payment: 1. Check the tax amount on the order. It was calculated with a rate your store no longer has. 2. If the tax looks wrong, start the sale on a new order — a new order picks up the store's current rates. **On the store (WP Admin)** — for the site administrator: 1. Go to **WooCommerce → Settings → Tax** and check whether a rate was deleted or edited recently. Deleting a rate that open orders already reference is the usual cause. 2. If a rate was removed on purpose, no action is needed beyond restarting any orders that were open at the time. 3. If the store's tax rates have not changed, the POS may be holding a stale copy. Refresh it from **Store health → Database → Tax rates → Clear & re-download** — this affects only that collection and does not log anyone out. See [Store health](/support/store-health.md#clear-and-redownload). 4. If the code returns once the tax rates have finished downloading, open the log entry in **Store health → Logs**, use **Copy** (or **Share**) to send its details, and contact support with the order number. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT421` (`ORDER_TAX_RATE_UNKNOWN`) * Severity warn * Introduced in WCPOS 1.10.0 --- # CHECKOUT999: Checkout unexpected ## What this means[​](#what-this-means "Direct link to What this means") Checkout hit an unexpected problem. Check the order in your store admin before charging the customer again. Export diagnostics and contact support if the problem repeats. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — verify before retrying. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Check WooCommerce → Orders in WP Admin for the order before charging the customer again. 2. Expand the log entry and note the event code and any serverCode — this generic code means the cause has no dedicated code yet. 3. If it repeats, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `CHECKOUT999` (`CHECKOUT_UNEXPECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # CLIENT101: App start failed ## What this means[​](#what-this-means "Direct link to What this means") WCPOS could not finish starting. From the till this looks like a blank or stuck screen, or a loading spinner that never clears. It usually means the device's local database could not be opened. Restarting sometimes clears it; if not, the fix is to clear the local database and reopen, and WCPOS re-downloads everything from your store. Clearing loses unsynced data Clearing the local database **permanently deletes anything on this device that has not yet synced to your store** — for example sales taken while offline. Because the app cannot open, these cannot be synced first, so they cannot be recovered. If you know important sales are still unsynced on this device, contact support **before** clearing. ## Your data[​](#your-data "Direct link to Your data") Your store's data is safe — it downloads again the next time the app opens. Clearing removes only this device's local copy, including any changes that had not yet reached your store (see the warning above). ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Restart the app once; on web, fully reload the tab — a transient startup failure often clears on its own. 2. If it still will not start, the local database most likely cannot be opened. Clear it and reopen — follow [Clear All Local Data](/support/troubleshooting/clear-local-data.md), which covers the in-app button, the web app, and the desktop app. WCPOS re-downloads your store's data automatically. (This deletes unsynced data on this device — see the warning above.) 3. If startup still fails after clearing, use **Copy debug info** — or the browser console error, if the app cannot open its own logs — and contact support. ## Details[​](#details "Direct link to Details") * Code `CLIENT101` (`APP_START_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # CLIENT111: App start slow ## What this means[​](#what-this-means "Direct link to What this means") Syncing is taking longer than expected to start. This usually resolves by itself within a minute. If the app stays in this state, reload it once before anything else. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Give it a minute — the first sync after an update, or on a large store, legitimately takes longer. 2. If the app stays in this state, reload it once. 3. If slow starts happen daily, check your connection to the store; if that is fine, ask whoever manages the store to check the site's own responsiveness. ## Details[​](#details "Direct link to Details") * Code `CLIENT111` (`APP_START_SLOW`) * Severity warn * Introduced in WCPOS 1.10.0 --- # CLIENT121: Multi tab limited ## What this means[​](#what-this-means "Direct link to What this means") This browser lets only one tab send changes at a time. You can keep using every tab — they all share the same local data. One tab quietly handles the syncing for all of them. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Keep using every tab normally — they share the same local data, and one tab quietly syncs on behalf of the rest. 2. This browser (or a private window) lacks the tab-coordination feature the POS prefers, so it falls back to a single syncing tab. No fix is needed. ## Details[​](#details "Direct link to Details") * Code `CLIENT121` (`MULTI_TAB_LIMITED`) * Severity warn * Introduced in WCPOS 1.10.0 --- # CLIENT131: Request queue overflow ## What this means[​](#what-this-means "Direct link to What this means") WCPOS queued too many requests at once and dropped some. This is usually an app defect rather than a store problem. Restart WCPOS; if the code returns, export diagnostics and contact support. ## Your data[​](#your-data "Direct link to Your data") Requests that already completed are safe. A dropped request simply did not run, so confirm the action you were part-way through actually completed before moving on. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Pause for a few seconds — the queue drains on its own and stale requests are dropped automatically. Confirm whether the action you were part-way through went through, and retry it only if it did not. 2. If it happens again in the same session, restart WCPOS; the queue clears on restart. 3. This is usually an app defect rather than a store problem: if it keeps returning, export debug info and contact support — the entry's context tells the developers which requests flooded the queue. ## Details[​](#details "Direct link to Details") * Code `CLIENT131` (`REQUEST_QUEUE_OVERFLOW`) * Severity error * Introduced in WCPOS 1.10.0 --- # CLIENT141: Search results did not match ## What this means[​](#what-this-means "Direct link to What this means") Local search returned results that do not match the catalogue; the app attempts an automatic search index rebuild. To answer searches instantly, WCPOS keeps a local search index of the lists it searches — products, customers, orders and similar. A self-check found entries in that index that do not actually match what was typed. The mismatched results were hidden straight away, and the app attempts one automatic index rebuild per list per session to correct the index itself. ## Your data[​](#your-data "Direct link to Your data") No store data was changed. This concerns only the local search index, which is derived from the data already on this device — hiding a mismatched result changes what search shows, never the underlying record. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Usually no action is needed, and sales can continue normally — but re-run the search named in the log entry (its context records the search term) and confirm the results now match what was typed, with nothing you expected missing. 2. If a product, customer or order you know exists is still missing from search results, reload the app — on web, reload the browser tab; on desktop and mobile, close and reopen the app. That lets it attempt a fresh index rebuild the next time the problem is detected. 3. If the code returns after a reload, export debug info and contact support — the entry's context names the list that was affected and the search that triggered it. ## Details[​](#details "Direct link to Details") * Code `CLIENT141` (`SEARCH_INDEX_DIVERGENCE`) * Severity error * Introduced in WCPOS 1.10.2 --- # CLIENT142: Search index did not answer ## What this means[​](#what-this-means "Direct link to What this means") The search index did not answer in time, so WCPOS searched the catalogue directly instead. The local search index was still building or could not answer. On web this is typically because the POS tab has been in the background, or because another tab holds the database lead; on desktop and mobile it typically happens right after a large sync, or in the moments after an app restart while the saved index is loading back in. Searches still answer, from a direct scan of the data on this device, and switch back to the index automatically once it responds. ## Your data[​](#your-data "Direct link to Your data") No store data was changed, and your search was still answered — a direct scan of this device's data answered it instead of the index. Searches may simply answer a little slower until the index takes over again. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Usually no action is needed: search results keep working, and the index takes over again on its own once it responds. 2. On web, if WCPOS is open in more than one browser tab, close the extra tabs — only one tab can lead the local database — and keep the POS in its own window rather than a background tab. 3. If searches stay slow or this code keeps appearing, reload the app once — on web, reload the browser tab; on desktop and mobile, close and reopen the app. 4. If the code still returns after that, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `CLIENT142` (`SEARCH_INDEX_STALLED`) * Severity warn * Introduced in WCPOS 1.10.5 --- # CLIENT143: Search index missed a record ## What this means[​](#what-this-means "Direct link to What this means") The search index could not find a product it should contain; the app attempts an automatic search index rebuild. A periodic self-check asked the local search index for a record by that record's own words, and the index did not return it. That means searches may have been showing fewer results than this device really holds. The app attempts one automatic index rebuild per list per session to correct it. ## Your data[​](#your-data "Direct link to Your data") No store data was changed. This concerns only the local search index, which is derived from the data already on this device — nothing is lost when it is rebuilt. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Usually no action is needed, and sales can continue normally: the app attempts a rebuild automatically and searches recover once it finishes. Only one rebuild is attempted per list per session, so if this code repeats, continue to the next step. 2. If search still misses records you can see in the app — a product, customer, order or other list — reload the app: on web, reload the browser tab; on desktop and mobile, close and reopen the app. That lets it attempt a fresh rebuild the next time the problem is detected. 3. If the code returns after a reload, export debug info and contact support — the log entry includes the details support needs to identify the affected list and the record the index missed. ## Details[​](#details "Direct link to Details") * Code `CLIENT143` (`SEARCH_INDEX_FALSE_MISS`) * Severity error * Introduced in WCPOS 1.10.5 --- # CLIENT144: Search index rebuild failed ## What this means[​](#what-this-means "Direct link to What this means") A search index rebuild failed, so results may be incomplete while the app retries initialization. After detecting a search index problem ([CLIENT141](/error-codes/CLIENT141.md) or [CLIENT143](/error-codes/CLIENT143.md)), the app tried to rebuild the index, and the rebuild itself failed. Search keeps answering — from the existing index with known bad results hidden, or from a direct scan of the data on this device — but it may miss or misrank results for the affected list. The next search or readiness check retries index initialization and can recover automatically; reloading the app is an optional fresh start if results remain wrong. ## Your data[​](#your-data "Direct link to Your data") No store data was changed. This concerns only the local search index, which is derived from the data already on this device. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Open the log entry — its context names the list affected and the error the rebuild hit. If that error mentions storage, free up space on the device first; on web, also avoid private/incognito windows. 2. Run another search on the affected list — the app retries index initialization automatically. 3. If results are still missing or wrongly ordered, reload the app: on web, reload the browser tab; on desktop and mobile, close and reopen the app. If CLIENT144 is logged again after that, export debug info from the Logs screen and contact support. ## Details[​](#details "Direct link to Details") * Code `CLIENT144` (`SEARCH_INDEX_REBUILD_FAILED`) * Severity warn * Introduced in WCPOS 1.10.6 --- # CLIENT201: Out of memory ## What this means[​](#what-this-means "Direct link to What this means") WCPOS ran out of memory and could not finish the operation. Restart WCPOS and retry once; export diagnostics if the device runs out of memory again. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — if you were saving something when the memory ran out, verify it completed before retrying. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Restart WCPOS. If you were saving something when the memory ran out, verify whether it completed before retrying — then retry once if it did not. 2. Close other apps or browser tabs — the POS shares the device's memory with everything else running on it. 3. If a specific action reliably runs out of memory, note what it was and contact support with debug info. 4. If this happens daily on the same device, the device may be too small for the catalogue — report it so support can confirm. ## Details[​](#details "Direct link to Details") * Code `CLIENT201` (`OUT_OF_MEMORY`) * Severity error * Introduced in WCPOS 1.10.0 --- # CLIENT211: Native crash ## What this means[​](#what-this-means "Direct link to What this means") WCPOS stopped because of a device-level crash. Restart WCPOS and export diagnostics if the crash repeats. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — if you were saving something when it crashed, verify it completed before retrying. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Restart WCPOS — the crash happened at device level, not in your data. 2. Install pending updates for the app and the device's operating system — native crashes are often already-fixed bugs. On a managed till, whoever manages the device does this. 3. If the crash repeats on the same action, export debug info and contact support, noting exactly what was tapped when it crashed. ## Details[​](#details "Direct link to Details") * Code `CLIENT211` (`NATIVE_CRASH`) * Severity error * Introduced in WCPOS 1.10.0 --- # CLIENT999: Unexpected error ## What this means[​](#what-this-means "Direct link to What this means") WCPOS encountered an unexpected error. Try the action once more, then export diagnostics and contact support if it fails again. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — verify before retrying. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Try the action once more. 2. Expand the log entry and note the event code and context — a 999 code means the failure has no dedicated code yet, and this is the information that identifies it. 3. If it repeats, export debug info and contact support — reporting it is how the specific code gets minted. ## Details[​](#details "Direct link to Details") * Code `CLIENT999` (`UNEXPECTED_ERROR`) * Severity error * Introduced in WCPOS 1.10.0 --- # Database Errors Database errors occur when storing or retrieving data in the local database. WCPOS uses a local database to store products, customers, and other data for fast access and offline functionality. These errors are prefixed with `DB`. ## Categories[​](#categories "Direct link to Categories") | Category | Code Range | Description | | -------------------------------- | ---------- | ------------------------------------------ | | [Connection](#connection-errors) | DB01xxx | Database connection and transaction issues | | [Data](#data-errors) | DB02xxx | Record and constraint issues | | [Query](#query-errors) | DB03xxx | Query syntax and data type issues | *** ## Connection Errors[​](#connection-errors "Direct link to Connection Errors") Issues connecting to or operating on the local database. | Code | Name | Description | | ---------------------------------- | ------------------ | --------------------------------------- | | [DB01001](/error-codes/DB01001.md) | Connection Failed | Could not connect to the local database | | [DB01002](/error-codes/DB01002.md) | Query Timeout | Database query took too long | | [DB01003](/error-codes/DB01003.md) | Transaction Failed | Database transaction could not complete | ## Data Errors[​](#data-errors "Direct link to Data Errors") Issues with records, duplicates, and constraints. | Code | Name | Description | | ---------------------------------- | -------------------- | ------------------------------------ | | [DB02001](/error-codes/DB02001.md) | Duplicate Record | A record with this ID already exists | | [DB02002](/error-codes/DB02002.md) | Record Not Found | The requested record does not exist | | [DB02003](/error-codes/DB02003.md) | Constraint Violation | Data violates database constraints | ## Query Errors[​](#query-errors "Direct link to Query Errors") Issues with query syntax and data types. | Code | Name | Description | | ---------------------------------- | ---------------------- | -------------------------------------- | | [DB03001](/error-codes/DB03001.md) | Query Syntax Error | The database query has syntax errors | | [DB03002](/error-codes/DB03002.md) | Invalid Data Type | Data type does not match expected type | | [DB03003](/error-codes/DB03003.md) | Missing Required Field | A required field is empty | --- # DB01001: Connection Failed ## What This Means[​](#what-this-means "Direct link to What This Means") The POS could not connect to its local database. WCPOS uses a local database to store products, customers, and other data for fast access and offline functionality. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Storage full** — Device has no storage space left * **Database corrupted** — Local database files are damaged * **Permission issue** — App doesn't have storage permissions * **Browser storage disabled** — IndexedDB is disabled (web version) ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Storage Space[​](#1-check-storage-space "Direct link to 1. Check Storage Space") Ensure your device has available storage: * Free up space if storage is full * Delete unused apps or files * Check available disk space ### 2. Clear App Data[​](#2-clear-app-data "Direct link to 2. Clear App Data") Reset the local database: * **Desktop app:** Look for "Clear Data" in settings * **Web browser:** Clear site data for the POS domain * **Note:** This will require re-syncing all data ### 3. Check Browser Settings (Web)[​](#3-check-browser-settings-web "Direct link to 3. Check Browser Settings (Web)") If using the web version: 1. Ensure IndexedDB is enabled 2. Don't use private/incognito mode (limited storage) 3. Allow the site to store data ### 4. Check Permissions[​](#4-check-permissions "Direct link to 4. Check Permissions") On desktop: * Ensure the app has permission to write to its data directory * Check if antivirus is blocking database access ### 5. Reinstall the App[​](#5-reinstall-the-app "Direct link to 5. Reinstall the App") If other solutions fail: 1. Uninstall the POS app 2. Restart your device 3. Reinstall the app 4. Login and sync data ## Data Recovery[​](#data-recovery "Direct link to Data Recovery") If you have unsaved data: * The app may have pending changes that couldn't be synced * Contact support if you need help recovering data * In most cases, data can be re-synced from the server ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB01002](/error-codes/DB01002.md) — Query Timeout * [SY01002](/error-codes/SY01002.md) — Disk Full --- # DB01002: Query Timeout ## What This Means[​](#what-this-means "Direct link to What This Means") A database operation took too long to complete. The local database query exceeded the maximum allowed time. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Large data set** — Very large number of products or records * **Complex query** — Query involving many conditions * **Device performance** — Device is running slowly * **Database fragmentation** — Database needs optimisation ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Wait and Retry[​](#1-wait-and-retry "Direct link to 1. Wait and Retry") The query may succeed on retry: * Close and reopen the POS * Try the operation again * Avoid other intensive operations simultaneously ### 2. Close Other Applications[​](#2-close-other-applications "Direct link to 2. Close Other Applications") Free up device resources: * Close unused browser tabs * Close other applications * Restart the device if needed ### 3. Reduce Data Scope[​](#3-reduce-data-scope "Direct link to 3. Reduce Data Scope") If searching: * Use more specific search terms * Apply filters to narrow results * Break large operations into smaller ones ### 4. Optimise the Database[​](#4-optimise-the-database "Direct link to 4. Optimise the Database") Clear and re-sync: 1. Clear local data (settings option if available) 2. Login again 3. Let data sync fresh ### 5. Check Device Performance[​](#5-check-device-performance "Direct link to 5. Check Device Performance") Ensure your device meets requirements: * Sufficient RAM * Adequate processor speed * SSD preferred over HDD ## Large Catalogues[​](#large-catalogues "Direct link to Large Catalogues") If you have a very large product catalogue: * Initial sync takes longer * Consider using filters in the POS * Some operations naturally take more time * Contact support for optimisation advice ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB01001](/error-codes/DB01001.md) — Connection Failed * [DB01003](/error-codes/DB01003.md) — Transaction Failed --- # DB01003: Transaction Failed ## What This Means[​](#what-this-means "Direct link to What This Means") A database transaction could not be completed. Transactions group multiple operations together — if any part fails, everything is rolled back to maintain data integrity. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Concurrent access** — Multiple operations trying to modify the same data * **Storage full** — No space to write new data * **Database locked** — Another process is locking the database * **Power interruption** — Operation interrupted unexpectedly ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Retry the Operation[​](#1-retry-the-operation "Direct link to 1. Retry the Operation") The issue may be temporary: * Wait a moment * Try the operation again * Avoid rapid repeated attempts ### 2. Check for Conflicts[​](#2-check-for-conflicts "Direct link to 2. Check for Conflicts") If multiple devices or tabs are open: * Use one instance at a time * Close duplicate browser tabs * Coordinate multi-device usage ### 3. Check Storage Space[​](#3-check-storage-space "Direct link to 3. Check Storage Space") Ensure there's space for data: * Check available disk space * Free up space if needed * Clear browser cache (web version) ### 4. Restart the Application[​](#4-restart-the-application "Direct link to 4. Restart the Application") Reset the database state: 1. Close the POS completely 2. Wait a few seconds 3. Reopen the application ### 5. Clear and Re-sync[​](#5-clear-and-re-sync "Direct link to 5. Clear and Re-sync") If transactions consistently fail: 1. Clear local data 2. Login again 3. Sync fresh from server ## Transaction Safety[​](#transaction-safety "Direct link to Transaction Safety") WCPOS uses transactions to ensure: * Data consistency * Complete operations (all or nothing) * Protection against partial updates When a transaction fails, your data remains consistent. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB01001](/error-codes/DB01001.md) — Connection Failed * [DB02003](/error-codes/DB02003.md) — Constraint Violation --- # DB02001: Duplicate Record ## What This Means[​](#what-this-means "Direct link to What This Means") The database tried to insert a record with an ID that already exists. Each record must have a unique identifier. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Sync conflict** — Same data synced twice * **Race condition** — Multiple operations creating same record * **Data corruption** — IDs were corrupted or duplicated * **Import issue** — Importing data that already exists ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Refresh Data[​](#1-refresh-data "Direct link to 1. Refresh Data") Re-sync from the server: * Pull latest data * Let the sync process resolve conflicts * The newer data should take precedence ### 2. Retry the Operation[​](#2-retry-the-operation "Direct link to 2. Retry the Operation") If creating new records: * The system may have already created it * Check if the record exists * Avoid clicking submit multiple times ### 3. Clear Local Cache[​](#3-clear-local-cache "Direct link to 3. Clear Local Cache") Reset local data: 1. Clear the local database/cache 2. Login again 3. Sync data fresh ### 4. Check for Duplicates in WooCommerce[​](#4-check-for-duplicates-in-woocommerce "Direct link to 4. Check for Duplicates in WooCommerce") If the issue persists: * Check WooCommerce for duplicate entries * Look for products/orders with same IDs * Clean up any duplicates in the admin ### 5. Report Persistent Issues[​](#5-report-persistent-issues "Direct link to 5. Report Persistent Issues") If this happens frequently: * Note what actions cause it * Check for patterns * Report to support with details ## Why This Matters[​](#why-this-matters "Direct link to Why This Matters") Duplicate IDs would cause: * Confusion about which record is correct * Data overwrites * Sync issues The error prevents data corruption. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB02002](/error-codes/DB02002.md) — Record Not Found * [DB02003](/error-codes/DB02003.md) — Constraint Violation --- # DB02002: Record Not Found ## What This Means[​](#what-this-means "Direct link to What This Means") The requested record does not exist in the local database. The POS tried to access a product, customer, order, or other record that isn't stored locally. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Not yet synced** — Data hasn't been downloaded yet * **Deleted on server** — Record was removed in WooCommerce * **Sync not complete** — Initial sync is still running * **Filter applied** — Record excluded by active filters ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Wait for Sync[​](#1-wait-for-sync "Direct link to 1. Wait for Sync") If recently started: * Wait for initial sync to complete * Check sync progress indicator * The record should appear once synced ### 2. Refresh/Re-sync[​](#2-refreshre-sync "Direct link to 2. Refresh/Re-sync") Trigger a data refresh: * Use the refresh/sync button () - short press for sync * **Long press** the sync button for Clear and Refresh option * Pull latest data from server * Wait for completion ### 3. Check WooCommerce[​](#3-check-woocommerce "Direct link to 3. Check WooCommerce") Verify the record exists on the server: * Log into WordPress Admin * Check Products, Orders, or Customers * Confirm the item still exists ### 4. Check Filters[​](#4-check-filters "Direct link to 4. Check Filters") The record might be filtered out: * Review active filters in the POS * Check category filters * Verify visibility settings ### 5. Clear and Re-sync[​](#5-clear-and-re-sync "Direct link to 5. Clear and Re-sync") If sync seems stuck: 1. Clear local data 2. Login again 3. Complete a fresh sync ## Common Scenarios[​](#common-scenarios "Direct link to Common Scenarios") * **Product not showing:** Check if it's published and visible * **Customer not found:** May not have been synced yet * **Order missing:** Could be outside the sync date range ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB02001](/error-codes/DB02001.md) — Duplicate Record * [API04004](/error-codes/API04004.md) — Missing Response Data --- # DB02003: Constraint Violation ## What This Means[​](#what-this-means "Direct link to What This Means") The data you're trying to save violates database rules. Constraints ensure data integrity by enforcing rules about what data can be stored. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Missing required data** — A required field is empty * **Invalid relationship** — Referencing a record that doesn't exist * **Data type mismatch** — Wrong type of data for the field * **Value out of range** — Number exceeds allowed limits ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Required Fields[​](#1-check-required-fields "Direct link to 1. Check Required Fields") Ensure all required data is provided: * Customer information (if required) * Product details * Order line items ### 2. Verify References[​](#2-verify-references "Direct link to 2. Verify References") If the error involves relationships: * Ensure referenced products exist * Check that customer IDs are valid * Verify category assignments ### 3. Review Data Values[​](#3-review-data-values "Direct link to 3. Review Data Values") Check for invalid values: * Negative quantities where not allowed * Prices exceeding limits * Invalid status values ### 4. Sync Latest Data[​](#4-sync-latest-data "Direct link to 4. Sync Latest Data") The referenced data may be out of sync: * Refresh data from server * Wait for sync to complete * Retry the operation ### 5. Clear and Retry[​](#5-clear-and-retry "Direct link to 5. Clear and Retry") If data is corrupted: 1. Clear the problematic form 2. Re-enter the data 3. Submit again ## Common Constraint Examples[​](#common-constraint-examples "Direct link to Common Constraint Examples") * **Quantity must be positive** — Can't add 0 or negative items * **Price must be numeric** — Text not allowed in price fields * **Customer must exist** — Can't assign order to non-existent customer ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB02001](/error-codes/DB02001.md) — Duplicate Record * [DB03003](/error-codes/DB03003.md) — Missing Required Field --- # DB03001: Query Syntax Error ## What This Means[​](#what-this-means "Direct link to What This Means") The database query has syntax errors. This typically indicates a bug in the application rather than a user error. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Software bug** — An issue in the POS application * **Version mismatch** — Incompatible data schema * **Corrupted data** — Data contains unexpected characters * **Encoding issues** — Character encoding problems ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Update the Application[​](#1-update-the-application "Direct link to 1. Update the Application") Ensure you're running the latest version: * Check for POS app updates * Update the WCPOS WordPress plugin * Restart after updating ### 2. Clear Application Data[​](#2-clear-application-data "Direct link to 2. Clear Application Data") Reset to a clean state: * Clear local data/cache * Login again * Re-sync data ### 3. Check for Special Characters[​](#3-check-for-special-characters "Direct link to 3. Check for Special Characters") If the error occurs with specific data: * Check for unusual characters in product names * Look for emojis or special symbols * Try with simpler data ### 4. Report the Bug[​](#4-report-the-bug "Direct link to 4. Report the Bug") If the issue persists: 1. Note what action causes the error 2. Capture any error details 3. Report on [GitHub](https://github.com/wcpos) ## This is Usually a Bug[​](#this-is-usually-a-bug "Direct link to This is Usually a Bug") Query syntax errors are typically bugs in the software, not user errors. If you encounter this: * You're not doing anything wrong * The development team needs to know * A fix will be released in an update ## Workaround[​](#workaround "Direct link to Workaround") Until a fix is available: * Try alternative approaches to accomplish your task * Use WooCommerce admin for affected operations * Check for updates regularly ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB03002](/error-codes/DB03002.md) — Invalid Data Type * [API03001](/error-codes/API03001.md) — Invalid Request Format --- # DB03002: Invalid Data Type ## What This Means[​](#what-this-means "Direct link to What This Means") The data type doesn't match what the database expects. For example, text was provided where a number was expected. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **User input error** — Entering text in a numeric field * **Import issues** — Imported data has wrong format * **Data corruption** — Values corrupted during transfer * **Plugin conflict** — Another plugin modified data types ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check Your Input[​](#1-check-your-input "Direct link to 1. Check Your Input") Review the data you're entering: * **Prices** — Should be numbers (e.g., `19.99`) * **Quantities** — Should be whole numbers (e.g., `5`) * **IDs** — Should be numeric ### 2. Clear and Re-enter[​](#2-clear-and-re-enter "Direct link to 2. Clear and Re-enter") If data was corrupted: * Clear the field * Enter the value again manually * Avoid copy-pasting from external sources ### 3. Check Source Data[​](#3-check-source-data "Direct link to 3. Check Source Data") If syncing from WooCommerce: * Check the data in WordPress Admin * Look for incorrectly formatted fields * Fix data at the source ### 4. Re-sync Data[​](#4-re-sync-data "Direct link to 4. Re-sync Data") Get fresh data from the server: * Clear local cache * Sync data again * Check if the issue resolves ### 5. Check for Plugin Conflicts[​](#5-check-for-plugin-conflicts "Direct link to 5. Check for Plugin Conflicts") If using other WooCommerce plugins: * They may modify data in unexpected ways * Temporarily disable to test * Report incompatibilities ## Common Examples[​](#common-examples "Direct link to Common Examples") | Field | Expected | Invalid | | ---------- | -------- | ----------------- | | Price | `19.99` | `$19.99` | | Quantity | `5` | `five` | | SKU | `ABC123` | — (any format OK) | | Product ID | `42` | `product-42` | ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB03003](/error-codes/DB03003.md) — Missing Required Field * [API03003](/error-codes/API03003.md) — Invalid Parameter Value --- # DB03003: Missing Required Field ## What This Means[​](#what-this-means "Direct link to What This Means") A required field was not provided. The database cannot save the record because essential information is missing. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Incomplete form** — Required fields weren't filled in * **Data sync issue** — Required data didn't sync properly * **Validation bypassed** — Form submitted without validation * **Custom field required** — A custom required field is empty ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Complete All Required Fields[​](#1-complete-all-required-fields "Direct link to 1. Complete All Required Fields") Check the form for: * Fields marked with asterisks (\*) * Highlighted or error-marked fields * Empty fields that should have values ### 2. Refresh and Re-enter[​](#2-refresh-and-re-enter "Direct link to 2. Refresh and Re-enter") If the form state is incorrect: 1. Refresh the page/screen 2. Re-enter all information 3. Verify all fields before submitting ### 3. Check WooCommerce Settings[​](#3-check-woocommerce-settings "Direct link to 3. Check WooCommerce Settings") If custom fields are required: 1. Review WooCommerce checkout settings 2. Check for required custom fields 3. Ensure the POS provides these fields ### 4. Sync Required Data[​](#4-sync-required-data "Direct link to 4. Sync Required Data") If related data is missing: * Refresh products/customers/etc. * Wait for sync to complete * Retry the operation ### 5. Review Required Field Settings[​](#5-review-required-field-settings "Direct link to 5. Review Required Field Settings") In WooCommerce Admin: * Check which fields are marked required * Consider if all are truly necessary for POS * Adjust requirements if needed ## Common Required Fields[​](#common-required-fields "Direct link to Common Required Fields") Typically required for orders: * At least one line item * Payment method * Customer (depending on settings) Typically required for products: * Product name * Price (for simple products) ## Related Errors[​](#related-errors "Direct link to Related Errors") * [DB02003](/error-codes/DB02003.md) — Constraint Violation * [API03002](/error-codes/API03002.md) — Missing Required Parameters --- # HOST101: Cors preflight blocked ## What this means[​](#what-this-means "Direct link to What this means") The server is blocking the browser's permission check (CORS preflight), so the web app cannot reach it. Browsers send an OPTIONS request before any cross-origin API call that carries custom headers. Something in front of this store — usually a firewall rule — is blocking OPTIONS, so the browser never sends the real request. Native apps are unaffected; the fix is server-side. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Check the firewall (WAF) for a rule blocking the OPTIONS method and allow it on /wcpos/ REST routes. 2. Some security plugins have a 'block uncommon request methods' toggle — OPTIONS must stay allowed. 3. Test: an OPTIONS request to the store's REST API should not return 403. 4. The desktop and mobile apps do not use CORS and will still work while this is being fixed. ## Details[​](#details "Direct link to Details") * Code `HOST101` (`CORS_PREFLIGHT_BLOCKED`) * Severity error * Introduced in WCPOS 1.10.0 --- # HOST111: Cors misconfigured ## What this means[​](#what-this-means "Direct link to What this means") The server's cross-origin (CORS) configuration is broken, so the browser refuses its responses. The store answers, but its CORS response headers are wrong — duplicated, set to the wrong origin, or missing on error responses. The browser then hides the real answer from the web app, which also masks every other error behind a generic network failure. The fix is server-side: exactly one Access-Control-Allow-Origin, present on every status code. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Look for a second CORS layer (a plugin AND the server config both adding headers) and remove one — duplicated Access-Control-Allow-Origin is a fatal browser error. 2. On nginx, add\_header lines skip error responses unless they end with 'always' — CORS headers must be on 4xx/5xx too. 3. If a CDN or proxy adds CORS headers, make sure it does not conflict with WordPress's own. 4. The desktop and mobile apps do not use CORS and will still work while this is being fixed. ## Details[​](#details "Direct link to Details") * Code `HOST111` (`CORS_MISCONFIGURED`) * Severity error * Introduced in WCPOS 1.10.0 --- # HOST121: Bot challenge blocking api ## What this means[​](#what-this-means "Direct link to What this means") A bot-protection page is answering instead of the store's API. The store's REST API is returning an HTML challenge page (bot protection, CAPTCHA, or DDoS interstitial) where the app expects JSON. A point-of-sale app cannot solve a browser challenge; the store's REST API needs to be allow-listed in the protection service. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Identify the protection layer from the challenge page (Cloudflare, Sucuri, Kinsta and others each brand theirs) and open its settings. 2. Allow-list the store's own REST API paths (/wp-json/ and /?rest\_route=) for API traffic. 3. On Cloudflare, add a WAF **Skip** rule for the REST API paths; Bot Fight Mode (Free plan) cannot be bypassed by any rule and must be turned off. The [Cloudflare guide](/support/troubleshooting/cloudflare.md) has the exact rule and a `curl` check. 4. In Kinsta's bot/firewall settings, allow-list the REST API paths; on Sucuri, avoid the JavaScript-challenge DDoS mode for API routes. ## Details[​](#details "Direct link to Details") * Code `HOST121` (`BOT_CHALLENGE_BLOCKING_API`) * Severity error * Introduced in WCPOS 1.10.0 --- # HOST131: Response headers rejected ## What this means[​](#what-this-means "Direct link to What this means") A proxy in front of the store rejects the server's responses for having too many headers. A cache or proxy layer (commonly Varnish) enforces a limit on response header count or size. The store's lightweight endpoints fit, but full API responses exceed the limit and come back as 503s from the proxy, not from WordPress. The limit must be raised on that layer. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. On Varnish, raise http\_max\_hdr (header count) and http\_resp\_hdr\_len / http\_resp\_size (sizes). 2. Ask the host which proxy layer returns the 503 — the WordPress error log will show nothing because the request never fails there. 3. A quick check: the store's /wcpos/v2/ping answers fine while data endpoints 503. ## Details[​](#details "Direct link to Details") * Code `HOST131` (`RESPONSE_HEADERS_REJECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # HOST141: Search blocked by waf ## What this means[​](#what-this-means "Direct link to What this means") The host's security filter is blocking product searches. A firewall rule on this host rejects REST requests whose query string contains non-ASCII characters or SQL-looking words. Product names with accents, and searches containing words like 'select' or 'union', will fail with a 403 even though they are ordinary catalogue searches. The till works otherwise; searches will be unreliable until the rule is relaxed. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Ask the host to allow-list the store's own REST search parameters (/wcpos/ and /wc/ routes) in the query-string firewall rules. 2. On OWASP CRS-based firewalls, the SQL-injection rules on the 's' and 'search' arguments are the usual culprits — exclude those arguments for REST API routes. 3. Security plugins with a 'filter suspicious query strings' toggle need an exception for the REST API, not a global off switch. ## Details[​](#details "Direct link to Details") * Code `HOST141` (`SEARCH_BLOCKED_BY_WAF`) * Severity warn * Introduced in WCPOS 1.10.0 --- # HOST151: Cache shared replay ## What this means[​](#what-this-means "Direct link to What this means") A cache in front of the store is replaying one person's API responses to everyone. A caching layer is serving stored REST API responses without checking who is asking: the app sent two differently-authenticated probes and received the first probe's answer both times. On a live store this means one cashier could see another's data, so connecting is blocked until the cache excludes the store's API. This is a hosting-layer problem — WordPress itself always answers per-user. ## Your data[​](#your-data "Direct link to Your data") Data on this device may be at risk — do not clear local data. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Exclude the store's REST API paths (/wp-json/ and /?rest\_route=) from page caching — on LiteSpeed disable REST caching or add a no-cache rule; on WP Engine extend the WooCommerce exclusion to /wp-json/wcpos; on Sucuri set the caching level to honor Cache-Control. 2. The store's API already sends Cache-Control: no-store and Vary: Authorization — the cache layer is ignoring them; point the host at those headers. 3. After changing cache settings, purge the cache before reconnecting. ## Details[​](#details "Direct link to Details") * Code `HOST151` (`CACHE_SHARED_REPLAY`) * Severity error * Introduced in WCPOS 1.10.0 --- # HOST161: Host rate limited ## What this means[​](#what-this-means "Direct link to What this means") The host is rate-limiting this store's tills. The server keeps answering 429 (too many requests) even though the app is already backing off and honoring the server's Retry-After delays. Several tills on one internet connection share one address, so per-source rate limits treat them as a single very busy client. Syncing continues automatically but will lag until the limit is raised. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Ask the host to raise or exempt the REST API rate limit for the store's own traffic — name the shop's static IP if it has one. 2. Security services that count repeated error responses (429s) toward a block (for example Sucuri's IDS) may need the store's API excluded from that counter. 3. If several tills share one connection, mention that to the host: one IP here is a whole shop, not one user. ## Details[​](#details "Direct link to Details") * Code `HOST161` (`HOST_RATE_LIMITED`) * Severity warn * Introduced in WCPOS 1.10.0 --- # LICENSE101: License not active here ## What this means[​](#what-this-means "Direct link to What this means") Your WCPOS Pro license is not active for this store or device. Check the local, licensing-server, and updater status, then activate the license for the named store. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **On the store** — for the site administrator / license holder: 1. Check the license status in the POS settings in WP Admin — it should show active for this store's exact URL. 2. A site URL change (http to https, adding or dropping www, a domain move, a staging copy) deactivates the license for the new address — re-activate it for the current one. 3. If the license shows active but the POS still disagrees, deactivate and re-activate it once. 4. Still locked? Export debug info and contact support with your license reference. **At the till:** after the license is re-activated, reload to pick up the change. ## Details[​](#details "Direct link to Details") * Code `LICENSE101` (`LICENSE_NOT_ACTIVE_HERE`) * Severity error * Introduced in WCPOS 1.10.0 --- # LICENSE201: Version skew Pro disabled ## What this means[​](#what-this-means "Direct link to What this means") WCPOS Pro is disabled because its version does not match WCPOS. Update the named WCPOS or WCPOS Pro component so both versions are compatible. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Check both plugin versions in WP Admin → Plugins — the log entry names which of WCPOS and WCPOS Pro is behind. 2. Update the older one; updating both to the latest versions resolves the skew. 3. If Pro updates are not being offered, the updater may not be authorized (see LICENSE301) — fix that first, then update. ## Details[​](#details "Direct link to Details") * Code `LICENSE201` (`VERSION_SKEW_PRO_DISABLED`) * Severity error * Introduced in WCPOS 1.10.0 --- # LICENSE301: Updater not authorized ## What this means[​](#what-this-means "Direct link to What this means") The updater is not authorized to download WCPOS Pro updates. Re-authorize the updater for this store, then check for updates again. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Re-enter or re-activate the license key in the POS settings so the updater can authenticate. 2. Check for updates again from WP Admin → Dashboard → Updates. 3. If authorization keeps failing, the site may be blocking outbound requests to the update server — ask the host whether outbound HTTPS is restricted. ## Details[​](#details "Direct link to Details") * Code `LICENSE301` (`UPDATER_NOT_AUTHORIZED`) * Severity error * Introduced in WCPOS 1.10.0 --- # LICENSE999: License unexpected ## What this means[​](#what-this-means "Direct link to What this means") License checking hit an unexpected problem. The POS keeps working. If Pro features stay locked, re-enter your license key, then contact support. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Keep working — the POS does not lock up over license checks. 2. If Pro features stay locked, re-enter the license key in the POS settings. 3. If that does not clear it, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `LICENSE999` (`LICENSE_UNEXPECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # PAYMENT101: Payment ok status check failed ## What this means[​](#what-this-means "Direct link to What this means") Payment succeeded, but WCPOS could not refresh its status afterward. The payment completed and should not be charged again; no action is required unless the displayed status stays stale. ## Your data[​](#your-data "Direct link to Your data") The payment succeeded — money moved. Do not charge the customer again; only the on-screen status is stale. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. No action is needed — the payment completed; only the follow-up status refresh failed. 2. Do not charge the customer again. 3. If the order's status looks stale on the till, reopen or sync the order; the store already has the correct status. ## Details[​](#details "Direct link to Details") * Code `PAYMENT101` (`PAYMENT_OK_STATUS_CHECK_FAILED`) * Severity info * Introduced in WCPOS 1.10.0 --- # PAYMENT201: Payment outcome unknown ## What this means[​](#what-this-means "Direct link to What this means") WCPOS could not confirm whether the terminal charged the payment. Check the payment terminal before attempting another charge, and contact the payment provider if the result remains unclear. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — verify before retrying. If this persists, contact your payment provider. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Do not run the card again yet. 2. Check the terminal's own screen, then your payment provider's dashboard — the provider's record is the authority on whether the charge went through. 3. If you have WP Admin access (or ask the store owner), check WooCommerce → Orders — a payment that succeeded may already be recorded there. 4. Only take payment again once the provider's dashboard shows no charge. 5. If the charge shows as pending or uncertain, contact the payment provider before acting. ## Details[​](#details "Direct link to Details") * Code `PAYMENT201` (`PAYMENT_OUTCOME_UNKNOWN`) * Severity error * Introduced in WCPOS 1.10.0 --- # PAYMENT301: Gateway unavailable ## What this means[​](#what-this-means "Direct link to What this means") The selected payment gateway is unavailable for this store. Ask the site administrator to verify that the gateway is supported, enabled, and correctly configured. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till:** complete the sale meanwhile with another method, such as cash. **On the store** — for the site administrator: 1. Check the gateway in WooCommerce → Settings → Payments: it must be installed, enabled, and enabled for POS use in the POS settings. 2. If the gateway worked yesterday, check whether it or WooCommerce updated — WooCommerce → Status → Logs may record gateway initialization errors. ## Details[​](#details "Direct link to Details") * Code `PAYMENT301` (`GATEWAY_UNAVAILABLE`) * Severity error * Introduced in WCPOS 1.10.0 --- # PAYMENT401: Terminal pairing incomplete ## What this means[​](#what-this-means "Direct link to What this means") The payment terminal did not finish pairing with WCPOS. This is usually a connectivity or pairing-state problem — the terminal is asleep, out of Bluetooth or network range, or still paired to another till. Wake it, bring it into range, and restart pairing; include the trace ID if you contact the payment provider. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, contact your payment provider. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Restart pairing on the terminal, keeping it awake and on the same network as the till. 2. Check the basics first: terminal charged, connected to the right network or Bluetooth, and not still paired to another till. 3. The log entry carries a trace ID — include it when contacting the payment provider if pairing still will not complete. ## Details[​](#details "Direct link to Details") * Code `PAYMENT401` (`TERMINAL_PAIRING_INCOMPLETE`) * Severity error * Introduced in WCPOS 1.10.0 --- # PAYMENT999: Payment unexpected ## What this means[​](#what-this-means "Direct link to What this means") Payment handling hit an unexpected problem. Confirm whether the payment went through before retrying. Export diagnostics and contact support if it is unclear. ## Your data[​](#your-data "Direct link to Your data") The outcome could not be confirmed — verify before retrying. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Confirm whether the payment went through before retrying: the terminal screen, the provider dashboard, and the order in WP Admin. 2. Expand the log entry for the event code and context — this generic code means the cause has no dedicated code yet. 3. If the outcome stays unclear or the code recurs, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `PAYMENT999` (`PAYMENT_UNEXPECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # PRINT101: Autoprint did not start ## What this means[​](#what-this-means "Direct link to What this means") Automatic printing did not start for this receipt. Check the selected printer, template, and connection, then use Print now to print the receipt manually. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Use Print now to print the receipt by hand — the sale is unaffected. 2. Check the printing settings: the right printer is selected and a receipt template is chosen. 3. If auto-print fails on every sale, note whether manual printing works — manual-works-but-auto-fails is a settings problem; both failing is a printer problem. ## Details[​](#details "Direct link to Details") * Code `PRINT101` (`AUTOPRINT_DID_NOT_START`) * Severity warn * Introduced in WCPOS 1.10.0 --- # PRINT201: Print job failed ## What this means[​](#what-this-means "Direct link to What this means") WCPOS could not confirm that the print job completed. Check the printer before retrying so the receipt is not printed twice. ## Your data[​](#your-data "Direct link to Your data") The sale and order data are safe and unchanged — only the print outcome is unconfirmed. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Look at the printer before retrying — the job may have printed even though no confirmation came back, and a blind retry prints the receipt twice. 2. Check paper, covers and error lights on the printer. 3. If nothing printed, retry once from the order's receipt screen. 4. For repeated failures, power-cycle the printer and check its connection to the till. ## Details[​](#details "Direct link to Details") * Code `PRINT201` (`PRINT_JOB_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # PRINT301: Printer unreachable ## What this means[​](#what-this-means "Direct link to What this means") The selected printer cannot be reached. Check that the printer is powered on and connected, then try printing again. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Check the printer is powered on and its cable or network connection is seated. 2. For network printers, confirm the till and printer are on the same network and the printer's address has not changed — DHCP renewals can move it; if it has, update the printer's address where you set it up in the POS. 3. Print a self-test from the printer itself to confirm the hardware works, then try again from the POS. ## Details[​](#details "Direct link to Details") * Code `PRINT301` (`PRINTER_UNREACHABLE`) * Severity error * Introduced in WCPOS 1.10.0 --- # PRINT311: Receipt delivery failed ## What this means[​](#what-this-means "Direct link to What this means") This receipt could not be emailed or downloaded. The sale itself is unaffected. Check the email address and the device's connection, then try again from the order's receipt screen. ## Your data[​](#your-data "Direct link to Your data") The order itself is safe and unchanged. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry to identify the delivery path: an email address or server status identifies email delivery; a templateId without an email identifies PDF generation, download, save or sharing. 2. For email delivery, check the address and connection, then resend from the order's receipt screen. If every email fails, ask the site administrator to check outgoing email and SMTP configuration. 3. For a PDF failure, retry Download PDF, check the device's free storage and download permissions, then choose a writable save location or another available share target. ## Details[​](#details "Direct link to Details") * Code `PRINT311` (`RECEIPT_DELIVERY_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # PRINT999: Print unexpected ## What this means[​](#what-this-means "Direct link to What this means") Printing hit an unexpected problem. Try printing again. If it keeps failing, reprint from the order screen and contact support with diagnostics. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry first and identify the failed operation — this code also covers receipt-email queue actions and receipt-template sync, not only physical printing. 2. Repeat only the operation named in the log. Reprint from the order screen only for a physical print attempt; retry or remove a queued email from Store health, and retry template sync by reopening the receipt screen while connected. 3. If that operation keeps failing, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `PRINT999` (`PRINT_UNEXPECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # PRODUCT101: Product save failed ## What this means[​](#what-this-means "Direct link to What this means") This product could not be saved to your store. Review the reported cause before retrying: reconnect for a network error, fix invalid fields, or refresh a conflicting product. ## Your data[​](#your-data "Direct link to Your data") Your edit stays on this device and will not reach the store until the reported cause is fixed. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry — the error text usually shows whether this was a network failure, a field the store rejected, or a conflicting edit made in the store. **At the till:** * Network failure: check the connection and retry; the edit is kept on this device. * Rejected field: correct the named field and retry. **On the store (WP Admin):** for a conflicting edit, open the product, compare versions, and re-apply the correct values. If saves keep failing with no clear reason, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `PRODUCT101` (`PRODUCT_SAVE_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # PRODUCT111: Variation add failed ## What this means[​](#what-this-means "Direct link to What this means") This variation could not be added to the product. Review and correct the variation fields, then retry; export diagnostics if it is still rejected. ## Your data[​](#your-data "Direct link to Your data") Your change stays on this device and will not reach the store until the rejection cause is corrected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry for the store's reason (serverCode) — usually a missing attribute or an invalid option combination. **At the till:** correct the variation's fields and retry. **On the store (WP Admin):** check the parent product's attributes — every attribute the variation uses must exist on the parent and be marked as used for variations. Still rejected? Export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `PRODUCT111` (`VARIATION_ADD_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # PRODUCT201: Product image unavailable ## What this means[​](#what-this-means "Direct link to What this means") This product image is unavailable, but the product can still be sold. Continue the sale without the image; WCPOS will try to load it again later. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till:** sell as normal — the product is unaffected and the image is retried in the background. **On the store (WP Admin):** 1. If one product's image never loads, re-save its image — the file may have been removed from the media library. 2. If many images fail at once, the site's media hosting or CDN is the cause — check whether images load on the store website itself. ## Details[​](#details "Direct link to Details") * Code `PRODUCT201` (`PRODUCT_IMAGE_UNAVAILABLE`) * Severity warn * Introduced in WCPOS 1.10.0 --- # PRODUCT301: Search no results reason ## What this means[​](#what-this-means "Direct link to What this means") A scan or typed search found no matching product. The usual causes are an active filter, a barcode that is missing or held in a different field, or a first sync that has not finished. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till:** 1. Clear the filters first — a category or stock filter silently narrows every search (a scanned code goes into the same search box). 2. Look the product up by name. If it appears but a scan missed it, its barcode in the store doesn't match the scanned value. If you typed the search, check spelling and stray spaces. 3. If the product is brand new, the local index may still be syncing — give the first sync time to finish, then try again. **On the store:** * If the barcode is missing, add the scanned value to the product's barcode field in WP Admin. * If every scan misses, the POS may be reading the wrong field — check which field your store keeps barcodes in, in the POS barcode settings. ## Details[​](#details "Direct link to Details") * Code `PRODUCT301` (`SEARCH_NO_RESULTS_REASON`) * Severity info * Introduced in WCPOS 1.10.0 --- # PRODUCT321: Barcode ambiguous ## What this means[​](#what-this-means "Direct link to What this means") More than one product matches this barcode. WCPOS cannot pick between them safely, so nothing was added. Search for the product by name, and give each product a unique barcode in the store to fix the clash. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask your store administrator. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till:** search for the product by name to complete this sale — the scan added nothing because the barcode matches more than one product. The log entry records the scanned code and how many products matched; searching the POS for the barcode value shows which ones they are. **On the store (WP Admin):** give each of those products its own unique barcode, then rescan to confirm only one match remains. ## Details[​](#details "Direct link to Details") * Code `PRODUCT321` (`BARCODE_AMBIGUOUS`) * Severity warn * Introduced in WCPOS 1.10.0 --- # PRODUCT401: Stock stale ## What this means[​](#what-this-means "Direct link to What this means") The displayed stock may be older than the store stock. Verify current stock in the store before completing a sale that could oversell the item. ## Your data[​](#your-data "Direct link to Your data") No data is at risk — the till's stock figure is simply older than the store's and catches up when sync recovers. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till:** before selling a low-stock item, confirm the real quantity — check the shelf or with your manager — rather than trusting the till's number, which may lag the store. **To fix the lag:** stale stock usually means sync has been failing or paused — check Store health → Logs for sync errors and resolve those. After sync recovers, the stock display catches up on its own. ## Details[​](#details "Direct link to Details") * Code `PRODUCT401` (`STOCK_STALE`) * Severity warn * Introduced in WCPOS 1.10.0 --- # PRODUCT411: Barcode config unavailable ## What this means[​](#what-this-means "Direct link to What this means") Barcode scanning settings could not be loaded, so scans may not match products. The POS keeps trying to load these settings in the background. If scanning stays unreliable, reload the app once. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Keep working — the POS retries loading the barcode settings in the background. 2. If scans keep matching nothing, reload the app once. 3. If it persists after a reload, the settings request itself is failing — check the connection to the store, and look for matching errors in Store health → Logs (ask whoever manages the store if you need help). ## Details[​](#details "Direct link to Details") * Code `PRODUCT411` (`BARCODE_CONFIG_UNAVAILABLE`) * Severity warn * Introduced in WCPOS 1.10.0 --- # PRODUCT421: Variable price meta invalid ## What this means[​](#what-this-means "Direct link to What this means") This product's variation price data could not be read, so displayed prices may be wrong or missing. Re-save the product in WooCommerce to rebuild its price data, or contact support if many products show this. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, ask your store administrator. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **At the till:** check the price before selling — if it looks wrong or is missing, don't sell at that price until it's corrected in the store. **On the store (WP Admin):** 1. Open the product and re-save it — this rebuilds the price data the POS could not read. 2. Check that each variation has a price set; a variation without a price produces unreadable price ranges. 3. If many products show this code at once, a pricing plugin is likely writing price data in a format the POS cannot read — note which plugin manages prices and contact support. ## Details[​](#details "Direct link to Details") * Code `PRODUCT421` (`VARIABLE_PRICE_META_INVALID`) * Severity warn * Introduced in WCPOS 1.10.0 --- # PRODUCT999: Product unexpected ## What this means[​](#what-this-means "Direct link to What this means") Loading or updating products hit an unexpected problem. Try again. If product data still looks wrong afterwards, export diagnostics and contact support. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Try again — most one-off product loading problems clear on retry. 2. If product data still looks wrong, expand the log entry for the event code and context; this generic code means the cause has no dedicated code yet. 3. Export debug info and contact support if it recurs. ## Details[​](#details "Direct link to Details") * Code `PRODUCT999` (`PRODUCT_UNEXPECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # Payment Errors Payment errors occur during checkout and payment processing. These errors are prefixed with `PY` and relate to issues with payment cards, gateways, and transactions. ## Categories[​](#categories "Direct link to Categories") | Category | Code Range | Description | | -------------------------- | ---------- | ------------------------------------ | | [Card](#card-errors) | PY01xxx | Issues with the payment card | | [Gateway](#gateway-errors) | PY02xxx | Payment gateway communication issues | *** ## Card Errors[​](#card-errors "Direct link to Card Errors") Issues related to the customer's payment card. | Code | Name | Description | | ---------------------------------- | ------------------- | -------------------------------- | | [PY01001](/error-codes/PY01001.md) | Payment Declined | The payment was declined | | [PY01002](/error-codes/PY01002.md) | Insufficient Funds | Not enough funds for the payment | | [PY01003](/error-codes/PY01003.md) | Card Expired | The payment card has expired | | [PY01004](/error-codes/PY01004.md) | Invalid Card Number | The card number is not valid | ## Gateway Errors[​](#gateway-errors "Direct link to Gateway Errors") Issues communicating with the payment gateway. | Code | Name | Description | | ---------------------------------- | --------------------- | ---------------------------------------- | | [PY02001](/error-codes/PY02001.md) | Payment Gateway Error | Error communicating with payment gateway | | [PY02002](/error-codes/PY02002.md) | Payment Timeout | Payment processing timed out | --- # PY01001: Payment Declined ## What This Means[​](#what-this-means "Direct link to What This Means") The payment was declined by the payment processor or card issuer. The transaction could not be completed. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Insufficient funds** — Not enough money in the account * **Card limit exceeded** — Transaction exceeds card limits * **Fraud protection** — Bank flagged as suspicious * **Incorrect card details** — Card number, CVV, or expiry wrong * **Card restrictions** — Card not enabled for this type of purchase ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Verify Card Details[​](#1-verify-card-details "Direct link to 1. Verify Card Details") Check that the entered information is correct: * Card number (all digits) * Expiration date * CVV/security code * Billing address (if required) ### 2. Try Again[​](#2-try-again "Direct link to 2. Try Again") Sometimes temporary issues occur: * Wait a moment * Re-enter the card details * Try the transaction again ### 3. Use a Different Payment Method[​](#3-use-a-different-payment-method "Direct link to 3. Use a Different Payment Method") If the card continues to decline: * Try a different card * Use cash payment * Use an alternative payment method ### 4. Contact the Bank[​](#4-contact-the-bank "Direct link to 4. Contact the Bank") The cardholder may need to: * Verify the transaction with their bank * Lift any fraud blocks * Confirm the card is active * Check for spending limits ### 5. Check for Restrictions[​](#5-check-for-restrictions "Direct link to 5. Check for Restrictions") Some cards have restrictions: * International transactions disabled * Online/POS transactions blocked * Certain merchant categories blocked ## For Store Owners[​](#for-store-owners "Direct link to For Store Owners") If you're seeing frequent declines: * Verify your merchant account is in good standing * Check payment gateway configuration * Review fraud prevention settings * Consider contacting your payment processor ## Related Errors[​](#related-errors "Direct link to Related Errors") * [PY01002](/error-codes/PY01002.md) — Insufficient Funds * [PY02001](/error-codes/PY02001.md) — Payment Gateway Error --- # PY01002: Insufficient Funds ## What This Means[​](#what-this-means "Direct link to What This Means") The payment was declined because there isn't enough money in the account to cover the transaction. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Low account balance** — Not enough funds available * **Pending transactions** — Other pending transactions reducing available balance * **Credit limit reached** — For credit cards, the limit is maxed out * **Hold on funds** — Funds are on hold for other transactions ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Use a Different Payment Method[​](#1-use-a-different-payment-method "Direct link to 1. Use a Different Payment Method") The quickest solution: * Try a different card * Use cash * Split payment across multiple methods (if supported) ### 2. Reduce the Order Amount[​](#2-reduce-the-order-amount "Direct link to 2. Reduce the Order Amount") If partial payment is possible: * Remove some items * Apply discounts or coupons * Complete a smaller transaction ### 3. Customer Actions[​](#3-customer-actions "Direct link to 3. Customer Actions") The customer may need to: * Transfer funds to the account * Wait for pending transactions to clear * Pay off credit card balance * Request a credit limit increase ### 4. Split the Transaction[​](#4-split-the-transaction "Direct link to 4. Split the Transaction") If your POS supports split payments: * Pay part with one card * Pay the remainder with another method ## Privacy Note[​](#privacy-note "Direct link to Privacy Note") When communicating this to customers: * Be discreet about the specific decline reason * Simply state "the card was declined" * Allow them to try another payment method privately ## Related Errors[​](#related-errors "Direct link to Related Errors") * [PY01001](/error-codes/PY01001.md) — Payment Declined * [PY01003](/error-codes/PY01003.md) — Card Expired --- # PY01003: Card Expired ## What This Means[​](#what-this-means "Direct link to What This Means") The payment card has passed its expiration date and can no longer be used for transactions. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Expired card** — The card's valid-through date has passed * **Incorrect expiry entered** — Expiration date was entered wrong * **New card not activated** — Replacement card received but not yet activated ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check the Expiration Date[​](#1-check-the-expiration-date "Direct link to 1. Check the Expiration Date") Look at the card: * Find the expiration date (MM/YY format) * Compare with current date * Verify the entered date matches the card ### 2. Use a Different Card[​](#2-use-a-different-card "Direct link to 2. Use a Different Card") If the card is truly expired: * Use a different, valid card * Use cash or alternative payment * Ask if customer has a replacement card ### 3. Get the Updated Card[​](#3-get-the-updated-card "Direct link to 3. Get the Updated Card") The cardholder should: * Check mail for a replacement card * Activate the new card if received * Contact their bank if no replacement arrived ### 4. Verify Entry[​](#4-verify-entry "Direct link to 4. Verify Entry") Double-check the expiration entry: * MM/YY format * Correct month and year * No typos ## Customer Service Tips[​](#customer-service-tips "Direct link to Customer Service Tips") When a card is expired: * Politely inform the customer * Suggest they check for a replacement card * Offer alternative payment options * Be understanding — this happens to everyone ## Related Errors[​](#related-errors "Direct link to Related Errors") * [PY01001](/error-codes/PY01001.md) — Payment Declined * [PY01004](/error-codes/PY01004.md) — Invalid Card Number --- # PY01004: Invalid Card Number ## What This Means[​](#what-this-means "Direct link to What This Means") The card number entered is not valid. Card numbers follow specific patterns and include check digits for validation. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Typo** — One or more digits entered incorrectly * **Missing digits** — Not all digits were entered * **Extra digits** — Too many digits entered * **Wrong card** — Different card number than physical card * **Card reader error** — Chip/swipe read the wrong data ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Re-enter the Card Number[​](#1-re-enter-the-card-number "Direct link to 1. Re-enter the Card Number") Carefully enter all digits: * Check the physical card * Enter each digit slowly * Verify the full number before submitting ### 2. Check Card Type[​](#2-check-card-type "Direct link to 2. Check Card Type") Ensure the card type is supported: * Visa (starts with 4) * Mastercard (starts with 51-55 or 22-27) * Amex (starts with 34 or 37) * Discover (starts with 6011, 622, 644-649, 65) ### 3. Try Again with Card Reader[​](#3-try-again-with-card-reader "Direct link to 3. Try Again with Card Reader") If using a chip/swipe reader: * Clean the card chip * Try a different read method (chip vs swipe) * Manually enter if reader fails ### 4. Use a Different Card[​](#4-use-a-different-card "Direct link to 4. Use a Different Card") If the card number continues to fail: * The card may be damaged * Try a different card * Use an alternative payment method ### 5. Check for Card Damage[​](#5-check-for-card-damage "Direct link to 5. Check for Card Damage") Physical card issues: * Scratched magnetic stripe * Damaged chip * Worn or faded numbers * Card may need replacement ## Card Number Formats[​](#card-number-formats "Direct link to Card Number Formats") | Card Type | Length | Starts With | | ---------- | ------ | ---------------------- | | Visa | 16 | 4 | | Mastercard | 16 | 51-55, 22-27 | | Amex | 15 | 34, 37 | | Discover | 16 | 6011, 622, 644-649, 65 | ## Related Errors[​](#related-errors "Direct link to Related Errors") * [PY01001](/error-codes/PY01001.md) — Payment Declined * [PY01003](/error-codes/PY01003.md) — Card Expired --- # PY02001: Payment Gateway Error ## What This Means[​](#what-this-means "Direct link to What This Means") An error occurred while communicating with the payment gateway. The payment processor couldn't complete the request. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Gateway downtime** — The payment service is experiencing issues * **Configuration error** — Gateway settings are incorrect * **API credentials** — Invalid or expired API keys * **Network issues** — Connection problems to the gateway ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Retry the Transaction[​](#1-retry-the-transaction "Direct link to 1. Retry the Transaction") Sometimes gateways have temporary issues: * Wait a moment * Try processing the payment again * The issue may resolve itself ### 2. Check Gateway Status[​](#2-check-gateway-status "Direct link to 2. Check Gateway Status") Visit your payment provider's status page: * Stripe: status.stripe.com * PayPal: Check PayPal community or status * Square: status.squareup.com * Check for known outages ### 3. Verify Gateway Configuration[​](#3-verify-gateway-configuration "Direct link to 3. Verify Gateway Configuration") In WooCommerce Admin: 1. Go to WooCommerce → Settings → Payments 2. Click on your payment gateway 3. Verify API keys are correct 4. Check that test/live mode matches your keys ### 4. Check API Credentials[​](#4-check-api-credentials "Direct link to 4. Check API Credentials") Ensure credentials are valid: * API keys haven't expired * Using live keys for live transactions * Using test keys for test transactions * Credentials match the correct account ### 5. Test with a Different Gateway[​](#5-test-with-a-different-gateway "Direct link to 5. Test with a Different Gateway") If available: * Try processing with an alternative gateway * Use cash payment as a fallback * Complete the sale and reconcile later ## For Store Owners[​](#for-store-owners "Direct link to For Store Owners") Common configuration issues: * Mixing test and live API keys * API keys from different accounts * Disabled payment methods * Expired or revoked credentials Contact your payment provider's support if the issue persists. ## Related Errors[​](#related-errors "Direct link to Related Errors") * [PY02002](/error-codes/PY02002.md) — Payment Timeout * [PY01001](/error-codes/PY01001.md) — Payment Declined --- # PY02002: Payment Timeout ## What This Means[​](#what-this-means "Direct link to What This Means") The payment processing took too long and timed out. The payment gateway didn't respond within the expected time. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Gateway overload** — Payment processor is experiencing high volume * **Network latency** — Slow connection to the payment service * **Processing delay** — Complex fraud checks or verification * **Server issues** — Payment gateway having performance issues ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Check if Payment Succeeded[​](#1-check-if-payment-succeeded "Direct link to 1. Check if Payment Succeeded") **Important:** Before retrying, verify the payment status: * Check your payment gateway dashboard * Look for the transaction in WooCommerce * Don't process again if it actually succeeded ### 2. Retry with Caution[​](#2-retry-with-caution "Direct link to 2. Retry with Caution") If the payment definitely didn't go through: * Wait 30-60 seconds * Try again * Watch for duplicate charges ### 3. Check Your Connection[​](#3-check-your-connection "Direct link to 3. Check Your Connection") Ensure stable connectivity: * Test your internet connection * Try a wired connection if on WiFi * Check for network issues ### 4. Try at a Less Busy Time[​](#4-try-at-a-less-busy-time "Direct link to 4. Try at a Less Busy Time") If the gateway is overloaded: * Retail peak times may cause slowdowns * Try again shortly * Use an alternative payment method ### 5. Contact Payment Provider[​](#5-contact-payment-provider "Direct link to 5. Contact Payment Provider") If timeouts persist: * Check their status page * Contact their support * Report ongoing issues ## Avoiding Duplicate Charges[​](#avoiding-duplicate-charges "Direct link to Avoiding Duplicate Charges") When a timeout occurs: 1. **Don't immediately retry** — Check the status first 2. **Review transactions** — Check both gateway and WooCommerce 3. **Refund duplicates** — Process refunds for any accidental duplicates 4. **Inform the customer** — Explain the situation if there's a delay ## Alternative Actions[​](#alternative-actions "Direct link to Alternative Actions") If payment keeps timing out: * Accept cash payment * Record as "pay later" if allowed * Use a different payment method ## Related Errors[​](#related-errors "Direct link to Related Errors") * [PY02001](/error-codes/PY02001.md) — Payment Gateway Error * [API01001](/error-codes/API01001.md) — Connection Timeout --- # System Errors System errors are related to device resources and system configuration. These errors are prefixed with `SY` and indicate issues with your device or the POS application itself. ## Categories[​](#categories "Direct link to Categories") | Category | Code Range | Description | | ---------------------------- | ---------- | -------------------------------------- | | [Resource](#resource-errors) | SY01xxx | Memory, disk, and permission issues | | [Service](#service-errors) | SY02xxx | Configuration and service availability | *** ## Resource Errors[​](#resource-errors "Direct link to Resource Errors") Issues with device resources like memory, storage, and permissions. | Code | Name | Description | | ---------------------------------- | ----------------- | ------------------------------- | | [SY01001](/error-codes/SY01001.md) | Out of Memory | Device is running low on memory | | [SY01002](/error-codes/SY01002.md) | Disk Full | Device storage is full | | [SY01003](/error-codes/SY01003.md) | Permission Denied | System permission was denied | ## Service Errors[​](#service-errors "Direct link to Service Errors") Issues with system configuration and service availability. | Code | Name | Description | | ---------------------------------- | --------------------- | ----------------------------------- | | [SY02001](/error-codes/SY02001.md) | Invalid Configuration | System configuration is invalid | | [SY02002](/error-codes/SY02002.md) | Service Unavailable | A required service is not available | --- # SY01001: Out of Memory ## What This Means[​](#what-this-means "Direct link to What This Means") Your device is running low on memory (RAM) and cannot complete the requested operation. The POS needs sufficient memory to function properly. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Too many apps open** — Other applications using memory * **Large data set** — Many products/customers loaded * **Memory leak** — Application not releasing memory properly * **Insufficient RAM** — Device doesn't have enough memory ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Close Other Applications[​](#1-close-other-applications "Direct link to 1. Close Other Applications") Free up memory: * Close unused browser tabs * Close other applications * Close background programs ### 2. Restart the POS[​](#2-restart-the-pos "Direct link to 2. Restart the POS") Refresh the application memory: 1. Close the POS completely 2. Wait a few seconds 3. Reopen the application ### 3. Restart Your Device[​](#3-restart-your-device "Direct link to 3. Restart Your Device") A full restart clears all memory: 1. Save any open work 2. Restart your computer/device 3. Open only the POS when starting again ### 4. Clear Browser Data (Web Version)[​](#4-clear-browser-data-web-version "Direct link to 4. Clear Browser Data (Web Version)") If using in a browser: * Clear browser cache * Close and reopen the browser * Use fewer browser tabs ### 5. Reduce Data Load[​](#5-reduce-data-load "Direct link to 5. Reduce Data Load") If you have a very large catalogue: * Use filters to load less data at once * Consider paginating results * Limit the sync scope if possible ## Minimum Requirements[​](#minimum-requirements "Direct link to Minimum Requirements") Ensure your device meets minimum specs: * **RAM:** 4GB minimum, 8GB recommended * **Browser:** Modern browser (Chrome, Firefox, Edge) * **Desktop App:** Check release notes for requirements ## Ongoing Issues[​](#ongoing-issues "Direct link to Ongoing Issues") If you frequently run out of memory: * Consider upgrading your device's RAM * Use a device with more resources * Report the issue if it seems excessive ## Related Errors[​](#related-errors "Direct link to Related Errors") * [SY01002](/error-codes/SY01002.md) — Disk Full * [DB01001](/error-codes/DB01001.md) — Connection Failed --- # SY01002: Disk Full ## What This Means[​](#what-this-means "Direct link to What This Means") Your device's storage is full. The POS cannot save data or continue operating without available disk space. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Storage full** — No free space on the drive * **Large local database** — POS data using significant space * **Temp files** — Temporary files consuming space * **Other applications** — Other apps filling the disk ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Free Up Disk Space[​](#1-free-up-disk-space "Direct link to 1. Free Up Disk Space") Delete unnecessary files: * Empty the trash/recycle bin * Remove old downloads * Delete unused applications * Clear temporary files ### 2. Check Available Space[​](#2-check-available-space "Direct link to 2. Check Available Space") **Windows:** * Open File Explorer * Right-click the drive → Properties * View used and free space **macOS:** * Apple menu → About This Mac * Click Storage ### 3. Clear Browser Data (Web Version)[​](#3-clear-browser-data-web-version "Direct link to 3. Clear Browser Data (Web Version)") Browsers store data locally: * Clear cache and cookies * Remove old site data * Check browser storage usage ### 4. Move or Delete Large Files[​](#4-move-or-delete-large-files "Direct link to 4. Move or Delete Large Files") Find and handle large files: * Old videos or photos * Large downloads * Unused software * Backup files that can be moved to external storage ### 5. Check POS Data[​](#5-check-pos-data "Direct link to 5. Check POS Data") If POS data is very large: * The local database may need cleaning * Consider clearing and re-syncing * Check if old data can be purged ## Recommended Free Space[​](#recommended-free-space "Direct link to Recommended Free Space") Keep at least: * **10GB** free for normal operation * **20GB+** for large catalogs * More space is always better ## Preventing Future Issues[​](#preventing-future-issues "Direct link to Preventing Future Issues") * Regularly clean up unnecessary files * Set up automatic temp file cleanup * Monitor disk space usage * Consider larger storage if frequently full ## Related Errors[​](#related-errors "Direct link to Related Errors") * [SY01001](/error-codes/SY01001.md) — Out of Memory * [DB01001](/error-codes/DB01001.md) — Connection Failed --- # SY01003: Permission Denied ## What This Means[​](#what-this-means "Direct link to What This Means") The POS application doesn't have permission to access a required resource. This could be a file, folder, or system feature. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **File permissions** — Can't read or write to needed files * **App permissions** — Application lacks required permissions * **Protected folder** — Trying to access a restricted location * **Security software** — Antivirus blocking access ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Run as Administrator (Windows)[​](#1-run-as-administrator-windows "Direct link to 1. Run as Administrator (Windows)") Right-click the app and select "Run as administrator" if needed for initial setup. ### 2. Check Application Permissions[​](#2-check-application-permissions "Direct link to 2. Check Application Permissions") **macOS:** * System Preferences → Security & Privacy → Privacy * Check that the app has necessary permissions **Windows:** * Settings → Privacy * Review app permissions ### 3. Check Folder Permissions[​](#3-check-folder-permissions "Direct link to 3. Check Folder Permissions") Ensure the app can access its data folder: * The user should own the app data directory * Write permissions should be enabled * No read-only flags on the folder ### 4. Review Antivirus Settings[​](#4-review-antivirus-settings "Direct link to 4. Review Antivirus Settings") Security software may block access: * Check antivirus logs for blocks * Add the POS app to the allowlist * Whitelist the app data folder ### 5. Reinstall the Application[​](#5-reinstall-the-application "Direct link to 5. Reinstall the Application") If permissions are corrupted: 1. Uninstall the POS application 2. Restart your device 3. Reinstall to a standard location 4. Run with normal (non-admin) permissions ## Browser Permissions (Web Version)[​](#browser-permissions-web-version "Direct link to Browser Permissions (Web Version)") If using the web version: * Allow local storage for the site * Enable cookies for the site * Don't use overly restrictive browser settings ## Related Errors[​](#related-errors "Direct link to Related Errors") * [SY01001](/error-codes/SY01001.md) — Out of Memory * [DB01001](/error-codes/DB01001.md) — Connection Failed --- # SY02001: Invalid Configuration ## What This Means[​](#what-this-means "Direct link to What This Means") The system configuration is invalid or corrupted. The POS application found configuration settings that don't make sense or are incomplete. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Corrupted settings** — Configuration file became corrupted * **Incomplete setup** — Setup process wasn't completed * **Manual editing error** — Config files were incorrectly modified * **Version upgrade issue** — Old config incompatible with new version ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Reset to Default Settings[​](#1-reset-to-default-settings "Direct link to 1. Reset to Default Settings") If available in the app: * Look for "Reset Settings" or "Restore Defaults" * This clears custom settings but fixes corruption ### 2. Complete the Setup[​](#2-complete-the-setup "Direct link to 2. Complete the Setup") If setup wasn't finished: 1. Start the setup process again 2. Complete all required steps 3. Verify configuration before finishing ### 3. Clear Application Data[​](#3-clear-application-data "Direct link to 3. Clear Application Data") Remove corrupted config: * **Desktop:** Delete app data folder, restart app * **Browser:** Clear site data, reload ### 4. Reinstall the Application[​](#4-reinstall-the-application "Direct link to 4. Reinstall the Application") For persistent issues: 1. Uninstall completely 2. Remove any leftover data folders 3. Reinstall fresh 4. Complete setup from scratch ### 5. Check for Updates[​](#5-check-for-updates "Direct link to 5. Check for Updates") Configuration formats may change: * Update the POS application * Update the WCPOS plugin * Reconfigure after update ## What Gets Reset[​](#what-gets-reset "Direct link to What Gets Reset") When resetting configuration: * You'll need to log in again * Custom settings will be lost * Data will need to re-sync * But your WooCommerce data is safe on the server ## Related Errors[​](#related-errors "Direct link to Related Errors") * [SY02002](/error-codes/SY02002.md) — Service Unavailable * [API06003](/error-codes/API06003.md) — Invalid Site Configuration --- # SY02002: Service Unavailable ## What This Means[​](#what-this-means "Direct link to What This Means") A required service or component is not available. The POS depends on various services to function, and one of them is currently inaccessible. ## Common Causes[​](#common-causes "Direct link to Common Causes") * **Background service stopped** — A required service isn't running * **System resource issue** — Not enough resources to start the service * **Dependency failure** — A service this depends on failed * **Startup issue** — Service failed to start properly * **Server error** — The WooCommerce server returned a 5xx error ## Server Error Mapping[​](#server-error-mapping "Direct link to Server Error Mapping") This error code is triggered when the server returns: | Server Code | Source | | ----------- | ---------------------------------------------------- | | HTTP 5xx | Any server error response (500, 502, 503, 504, etc.) | ## How to Fix[​](#how-to-fix "Direct link to How to Fix") ### 1. Restart the Application[​](#1-restart-the-application "Direct link to 1. Restart the Application") Close and reopen the POS: 1. Fully close the application 2. Wait a few seconds 3. Start it again ### 2. Restart Your Device[​](#2-restart-your-device "Direct link to 2. Restart Your Device") A full restart often resolves service issues: 1. Save any important work 2. Restart your computer 3. Try the POS again ### 3. Check System Resources[​](#3-check-system-resources "Direct link to 3. Check System Resources") Ensure system resources are available: * Close unnecessary applications * Check memory usage * Check disk space ### 4. Update the Application[​](#4-update-the-application "Direct link to 4. Update the Application") Ensure you're on the latest version: * Check for available updates * Install any pending updates * Restart after updating ### 5. Reinstall if Necessary[​](#5-reinstall-if-necessary "Direct link to 5. Reinstall if Necessary") If the service remains unavailable: 1. Uninstall the application 2. Restart your device 3. Download the latest version 4. Install fresh ## Browser-Specific (Web Version)[​](#browser-specific-web-version "Direct link to Browser-Specific (Web Version)") For the web version: * Ensure JavaScript is enabled * Check that required browser features aren't blocked * Try a different browser * Disable browser extensions that might interfere ## When to Contact Support[​](#when-to-contact-support "Direct link to When to Contact Support") If this error persists: * Note when it occurs * Check if specific actions trigger it * Report with details for investigation ## Related Errors[​](#related-errors "Direct link to Related Errors") * [SY02001](/error-codes/SY02001.md) — Invalid Configuration * [API01008](/error-codes/API01008.md) — Website Unavailable --- # SYNC101: Local DB write failed ## What this means[​](#what-this-means "Direct link to What this means") This change could not be saved to the local database and remains only on this device. Do not clear or reload local data. First write down (or re-enter) the change that failed to save — a restart can lose it — then check the device's storage. If writes keep failing, export diagnostics and contact support. ## Your data[​](#your-data "Direct link to Your data") Data on this device may be at risk — do not clear local data. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. If the log entry names a record, note it — that is the change that has not been saved. Site and credential writes may name only the failed operation and error instead; record those details before continuing. 2. Do not clear site data, reset the app, or uninstall: the unsaved change exists only on this device, and clearing local storage deletes it permanently. 3. Check the device's free storage — a full disk or an exhausted browser storage quota is the most common reason a local write fails. 4. Restart WCPOS once and make a small, harmless edit to confirm whether new changes save. 5. If writes keep failing, use Copy debug info on the Logs screen and contact support before attempting any repair. ## Details[​](#details "Direct link to Details") * Code `SYNC101` (`LOCAL_DB_WRITE_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC111: Local DB corrupted ## What this means[​](#what-this-means "Direct link to What this means") Local store data is damaged and needs repair before syncing can continue. Run the targeted repair for the affected data, and reset that local data only if the problem returns. ## Your data[​](#your-data "Direct link to Your data") Data on this device may be at risk — do not clear local data. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Open Store health → Database and run the targeted repair for the affected data; a full reset discards more than the repair does. 2. Retry the action that failed, then watch Store health → Logs for a repeat of this code. 3. If the same data is flagged again, reset just that local data so it downloads fresh from your store — but only after any unsent changes have been noted. 4. Corruption that keeps returning points at failing device storage: export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `SYNC111` (`LOCAL_DB_CORRUPTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC121: Sync unreachable ## What this means[​](#what-this-means "Direct link to What this means") Your store cannot be reached right now, so changes will stay on this device. Check the connection and keep working offline; syncing will retry automatically when the store is reachable. ## Your data[​](#your-data "Direct link to Your data") The change is saved on this device but has not reached your store. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Keep selling — sales are saved on this device and sync resumes automatically once the store answers. 2. Check whether the till itself is online: can any other website load from this device? 3. Open your store's own website in a browser tab on the same device; if it does not load there either, the site or its hosting is down, not the POS. 4. **For whoever manages this device's network:** if the site loads but the POS stays offline, something between the two is blocking API requests — a VPN, firewall, ad-blocker or security plugin. The browser's developer tools (Network tab) — or **Advanced → Toggle Developer Tools** in the desktop app — show which request fails. ## Details[​](#details "Direct link to Details") * Code `SYNC121` (`SYNC_UNREACHABLE`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC131: Store server error ## What this means[​](#what-this-means "Direct link to What this means") Your store returned an error, so this action did not complete. The store was reached but its server failed to handle the request. This is a problem on the website rather than the POS, so retrying alone may not help: check the site's error log or ask the host to, then retry. Nothing was lost on this device. ## Your data[​](#your-data "Direct link to Your data") The change is saved on this device but has not reached your store. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") **On the POS (cashier):** expand the log entry and note the status, endpoint and serverCode — they say what the server was doing when it failed. **On the website (site admin / host):** 1. Open WooCommerce → Status → Logs on the site and check the newest fatal-errors log around the failure time; a 500-class response almost always leaves a PHP error there. 2. If the failure started after a plugin, theme or PHP update on the site, suspect that change first and roll it back or disable it. 3. If WooCommerce's logs show nothing, ask the hosting provider for the server's PHP error log for the same time window. **Then, back on the POS:** once the server-side cause is fixed, retry — the change is still saved on this device. ## Details[​](#details "Direct link to Details") * Code `SYNC131` (`STORE_SERVER_ERROR`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC141: Store rate limited ## What this means[​](#what-this-means "Direct link to What this means") Your store is limiting requests temporarily, so this action will retry later. Wait before retrying. If rate limits continue, ask the site administrator or host to review the store's request limits. ## Your data[​](#your-data "Direct link to Your data") The change is saved on this device but has not reached your store. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Wait — the POS backs off and retries by itself; retrying by hand only extends the throttle. 2. Nothing needs to be re-entered: the affected changes stay on the device and go through on a later attempt. 3. If the code keeps appearing, ask the site administrator to find which layer returns the 429 — a security plugin, a CDN or firewall rule, or the host's own limits — and to allow the POS's REST traffic. 4. The expanded log entry's endpoint and timestamps help the administrator match the throttle in their own dashboards. ## Details[​](#details "Direct link to Details") * Code `SYNC141` (`STORE_RATE_LIMITED`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC151: Store response malformed ## What this means[​](#what-this-means "Direct link to What this means") Your store sent a malformed response that WCPOS had to repair before reading. This usually means a plugin or PHP notice is printing extra output into store responses. WCPOS recovered this one, but repairs are not guaranteed — ask the site administrator to check the site's error log. ## Your data[​](#your-data "Direct link to Your data") The malformed response was repaired for reading. If the underlying request itself failed (see Troubleshoot step 1), follow that request's guidance; otherwise no order or product data is affected. If this persists, ask the person who manages your WordPress site. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Check whether the related request ultimately succeeded. If it did, WCPOS repaired this occurrence; if it failed, follow that request's error and retry guidance instead. 2. The cause is on the site: a plugin or theme is printing warnings or stray output into REST responses. Ask the site administrator to check the site's logs for PHP notices at the failure time. 3. The browser's developer tools (Network tab) — or **Advanced → Toggle Developer Tools** in the desktop app — show the raw response body; the stray output is visible immediately before or after the JSON. 4. Repairs are best-effort: if these warnings become frequent, fix the offending plugin rather than relying on the repair. ## Details[​](#details "Direct link to Details") * Code `SYNC151` (`STORE_RESPONSE_MALFORMED`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC161: Local DB unavailable ## What this means[​](#what-this-means "Direct link to What this means") The local database on this device stopped responding, so actions that need it are paused. Restart WCPOS to reconnect the local database. Unsaved changes on this device may not have been written; check recent orders after restarting. If it keeps happening, export diagnostics and contact support. ## Your data[​](#your-data "Direct link to Your data") Data on this device may be at risk — do not clear local data. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Restart WCPOS — closing and reopening the app (or the browser tab) reconnects the local database in almost all cases. 2. After restarting, check the most recent orders: a change made in the seconds before the failure may not have been written. 3. On web, avoid private/incognito windows and aggressive storage-cleaning extensions — both can tear down local storage mid-session. 4. If this returns regularly on the same device, export debug info and contact support, noting what the device was doing (sleep, tab switch, low memory) when it happened. ## Details[​](#details "Direct link to Details") * Code `SYNC161` (`LOCAL_DB_UNAVAILABLE`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC171: Local DB setup failed ## What this means[​](#what-this-means "Direct link to What this means") A local database on this device could not be created or removed. Restart WCPOS and try again. If it keeps failing, the device may be low on storage or the browser profile may be restricting storage; free up space, then contact support if it persists. ## Your data[​](#your-data "Direct link to Your data") The device's local database could not be set up or cleared. This is a storage/setup problem, not an unsynced edit — free up storage and retry; if it persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Restart WCPOS and try the same action again — most setup failures are transient. 2. Check free storage on the device; creating a local database fails outright when the disk or the browser's storage quota is full. 3. On web, check that the browser allows persistent storage for the site — private windows and block-all-data settings do not. 4. If it keeps failing, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `SYNC171` (`LOCAL_DB_SETUP_FAILED`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC181: Local database call stalled ## What this means[​](#what-this-means "Direct link to What this means") A local database operation is taking far longer than normal; its outcome is not yet known. A single read or write to the local database on this device has gone unanswered for far longer than normal, while the database keeps answering everything else. This reporter only records the stall — it does not cancel or retry the operation, so the original call may still complete or fail later; the entry exists so a stuck screen or spinner leaves a trace naming exactly which operation stalled. Stalled sync work has a separate timeout and retry path — logged as a "Gave up on a stuck data request" entry under [SYNC321](/error-codes/SYNC321.md). A stalled call from a screen stays pending until it finishes or the app is reloaded. ## Your data[​](#your-data "Direct link to Your data") The stalled operation is usually a lookup, which changes nothing. If a change was being saved at that moment, open the record and confirm it saved — there may have been no visible symptom at all. The entry's context names the operation and the data collection involved. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. If everything is working, no action is needed — the call most likely completed, just slowly. 2. If a screen or spinner stays stuck, reload the app — on web, reload the browser tab; on desktop and mobile, close and reopen the app. That abandons the stuck operation; the screen loads again and asks the database fresh. A save that was in flight is not resent — open the record and confirm it saved. 3. If this code returns regularly on the same device, export debug info from the Logs screen and contact support — the entry's context names the operation and collection, the exact wait, and how busy the database was meanwhile. ## Details[​](#details "Direct link to Details") * Code `SYNC181` (`LOCAL_DB_STALLED`) * Severity warn * Introduced in WCPOS 1.10.6 --- # SYNC201: Record rejected ## What this means[​](#what-this-means "Direct link to What this means") This record was rejected by your store and is saved only on this device. Correct the reason shown for the named record, then retry it. Export diagnostics if it remains rejected. ## Your data[​](#your-data "Direct link to Your data") The change is saved on this device but has not reached your store. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry: it names the rejected record and carries the store's own reason (serverCode) for refusing it. 2. Rejected records are listed in Store health — open the record, correct the detail the store refused, and retry it from there. 3. **Site admin:** if the reason mentions a field the POS does not show, open the same record in WP Admin and check it there — another plugin may have added validation the POS cannot see. 4. If it stays rejected after editing, use Copy debug info and contact support, including the serverCode. ## Details[​](#details "Direct link to Details") * Code `SYNC201` (`RECORD_REJECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC211: Record invalid field ## What this means[​](#what-this-means "Direct link to What this means") A field on a record was rejected by your store. Occasionally this code also stands for a settings or authentication request the store refused. If it names a record, fix the named field and retry; the local copy remains available until it syncs. Otherwise, follow the store's message for the named request. ## Your data[​](#your-data "Direct link to Your data") If this was a record change, it is still saved on this device and has not reached your store. A settings or authentication request leaves nothing to save. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry and check the endpoint and server response first: this code can also represent an HTTP 400 from a settings, authentication or other non-record request. 2. If the context names a record or field, edit that field in the POS — common causes are a value out of range, a rejected format or a required option left empty — then retry. 3. If it is not a record request, follow the server's message for the named endpoint instead. The browser's developer tools (Network tab) — or **Advanced → Toggle Developer Tools** in the desktop app — show the response when the details are not in the POS log. 4. **Site admin:** if a named field looks correct in the POS, compare it with the same record in WP Admin — plugin-added validation on the store can reject values the POS considers fine. ## Details[​](#details "Direct link to Details") * Code `SYNC211` (`RECORD_INVALID_FIELD`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC221: Record conflict ## What this means[​](#what-this-means "Direct link to What this means") A change on this device clashed with an edit made in your store. Open the record and check which version is correct. The POS keeps both sides safe until the clash is settled — nothing is lost. ## Your data[​](#your-data "Direct link to Your data") The record itself is safe and unchanged — the POS keeps both the till's and the store's versions until the clash is settled. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Open the record named in the log entry and compare it with the store's copy in WP Admin (a site admin may need to do this). 2. Decide which version is right — the till's or the store's — and re-apply the correct values once; the POS keeps both sides safe, and further edits to that record are held until the clash is settled. 3. Frequent conflicts on the same records usually mean two people edit the same data in parallel; agree on where each kind of edit happens. ## Details[​](#details "Direct link to Details") * Code `SYNC221` (`RECORD_CONFLICT`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC301: Sync behind head ## What this means[​](#what-this-means "Direct link to What this means") Some older store changes were skipped and must be downloaded again. Run a targeted download for the affected data and export diagnostics if the gap remains. ## Your data[​](#your-data "Direct link to Your data") Some store changes have not yet reached this device, so local data may be out of date until the download completes. No local changes are at risk. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry — its context records how far behind the till fell and whether changes were skipped. 2. Run a targeted download for the affected data so the skipped store changes are fetched again. 3. Afterwards, spot-check a few recently-edited records against WP Admin to confirm the gap closed. 4. If the gap reappears, export debug info and contact support rather than resetting anything. ## Details[​](#details "Direct link to Details") * Code `SYNC301` (`SYNC_BEHIND_HEAD`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC311: Schema mismatch ## What this means[​](#what-this-means "Direct link to What this means") The data stored on this device is from a different version of the app and cannot be opened. The fix is to clear the device's local database and reopen — WCPOS then re-downloads everything from your store. A schema mismatch usually follows an app update or downgrade on this device. Clearing loses unsynced data Clearing the local database **permanently deletes anything on this device that has not yet synced to your store** — for example sales taken while offline. Because the database will not open, these cannot be synced first, so they cannot be recovered. If you know important sales are still unsynced on this device, contact support **before** clearing. ## Your data[​](#your-data "Direct link to Your data") Your store's data is safe — it downloads again the next time the app opens. Only the device's local copy is cleared, including any changes that had not yet reached your store (see the warning above). ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Make sure WCPOS is on the current version on this device — a schema mismatch usually follows a version change. 2. Clear the local database and reopen — follow [Clear All Local Data](/support/troubleshooting/clear-local-data.md), which covers the in-app button, the web app, and the desktop app. WCPOS re-downloads your store's data automatically. (This deletes unsynced data on this device — see the warning above.) 3. If the error returns after clearing, use **Copy debug info** and contact support. ## Details[​](#details "Direct link to Details") * Code `SYNC311` (`SCHEMA_MISMATCH`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC321: Sync partial ## What this means[​](#what-this-means "Direct link to What this means") Some records synced, but one or more records did not. This code appears in two forms — the log row's title says which one you have: * **"Sync partial"** (record titles): some records synced and the named records did not. Review each named record and its reason before retrying only those records. * **"Gave up on a stuck data request"**: the sync engine's data-request lane stopped making progress on one request, so after a generous wait the app abandoned that request rather than let it block everything queued behind it. Nothing needs retrying by hand — the sync engine re-issues the request automatically — and it often follows a stalled local database call, logged separately as [SYNC181](/error-codes/SYNC181.md). ## Your data[​](#your-data "Direct link to Your data") For records that did not sync: the change is saved on this device but has not reached your store. If this persists, export diagnostics and contact WCPOS support. For a gave-up data request: nothing was changed — an abandoned request is re-issued automatically. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. For a partial sync: expand the log entry to list which records did not sync and the reason each one gives. 2. Handle each named record by its own reason — an invalid field needs editing, a conflict needs comparing with the store. 3. Retry only the records that failed; the rest are already synced and need nothing. 4. For a "Gave up on a stuck data request" entry, no action is needed unless the screen stays stuck — then reload the app, and if it keeps happening, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `SYNC321` (`SYNC_PARTIAL`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC331: Local record diverged ## What this means[​](#what-this-means "Direct link to What this means") This record on the device does not match your store and needs local repair. Nothing you entered is waiting to be sent. The device's copy of a record your store owns has drifted from the store's copy; repair it according to the status shown in the log. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Expand the log entry - its context names the collection, the record id, the status and the detector that spotted the difference. 2. For a changed or missing record, run a targeted download for the affected collection so the device replaces its copy with the store's. 3. For a deleted record, remove the local copy; the server tombstone must not be downloaded. 4. Compare the record in WP Admin with what the POS shows; a price or stock difference is the visible symptom. 5. If the SAME records keep reappearing after repair, the store's stored digests are stale - this happens after a bulk write that skips WooCommerce's save hooks (a CSV import, a migration plugin, WP-CLI or direct SQL). The record itself is usually fine; WCPOS schedules a rebuild of the integrity index automatically once a range keeps reporting the same difference, and a site administrator can trigger it sooner. 6. If it still returns after a rebuild, export debug info and contact support. ## Details[​](#details "Direct link to Details") * Code `SYNC331` (`LOCAL_RECORD_DIVERGED`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC341: App update required ## What this means[​](#what-this-means "Direct link to What this means") This store now requires a newer version of the POS app. Your store's WCPOS plugin has moved to a newer sync protocol than this version of the app speaks, and the store deliberately pauses syncing until the app is updated. This is a protection, not a fault: it stops an out-of-date app from reading or writing store data incorrectly. ## Your data[​](#your-data "Direct link to Your data") Nothing on the till is lost. Sales and edits waiting to be sent stay safely on the device and sync once an updated app connects to the store. If no newer app exists yet (see the last two steps below), they stay queued until one does. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. On the web app, reload the browser tab — the web app picks up the new version on reload. If the screen comes back, use a hard reload (hold **Shift** while reloading). 2. On desktop, install the pending update and reopen the app — the check runs when the app reconnects. If no update is offered, download the latest build from the [Installation](/getting-started/installation.md) page. 3. On iPhone, iPad or Android, update WCPOS through the channel you installed it from — TestFlight on iOS, the Play testing programme on Android; both are linked from the [Installation](/getting-started/installation.md) page — then reopen the app. 4. **Site administrator:** if no newer app is available yet, the store's WCPOS plugin was updated ahead of the matching app release. Restoring the previous WCPOS plugin version on the store resumes syncing until the newer app ships. 5. If neither an app update nor a plugin rollback is available to you, contact WCPOS support. ## Details[​](#details "Direct link to Details") * Code `SYNC341` (`APP_UPDATE_REQUIRED`) * Severity error * Introduced in WCPOS 1.10.3 --- # SYNC401: Sync task crashed ## What this means[​](#what-this-means "Direct link to What this means") A background sync task stopped unexpectedly before finishing. The POS restarts these tasks automatically and no order data is affected. If this code keeps appearing, export diagnostics and contact support. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Nothing to do on first sight: the POS restarts the crashed background task automatically and no order data is involved. 2. If the code repeats within minutes, reload the app once so the sync engine starts clean. 3. If it still repeats, export debug info and contact support — a recurring task crash is an app defect worth reporting, not a store problem. ## Details[​](#details "Direct link to Details") * Code `SYNC401` (`SYNC_TASK_CRASHED`) * Severity error * Introduced in WCPOS 1.10.0 --- # SYNC411: Demand request flood ## What this means[​](#what-this-means "Direct link to What this means") This device asked the store for data far more often than normal. Nothing was slowed down or blocked, and no order data is affected — this is a detection-only alarm. Sustained request floods usually indicate an app problem (a screen re-requesting the same data in a loop) rather than anything you did. If this code keeps appearing, export diagnostics and contact support so the loop can be found and fixed. ## Your data[​](#your-data "Direct link to Your data") No order or product data is affected. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Keep working — this is a detection-only alarm. WCPOS does not slow, queue or drop any request, and no order or product data is affected. 2. If the code appears once and stops, no action is needed. If it repeats, note which screen was open and which action you were taking when it appeared. 3. Use Copy debug info while the event is still in the log window and contact WCPOS support; the export lets support trace the request loop. ## Details[​](#details "Direct link to Details") * Code `SYNC411` (`DEMAND_REQUEST_FLOOD`) * Severity warn * Introduced in WCPOS 1.10.0 --- # SYNC999: Sync unexpected ## What this means[​](#what-this-means "Direct link to What this means") Syncing hit an unexpected problem. Sales already recorded on this device are safe. Check the log first (see Troubleshoot): this may retry automatically, or — if a write never reached the queue — need re-entering. If this code keeps appearing, export diagnostics and contact support. ## Your data[​](#your-data "Direct link to Your data") If your entry was captured, it is safe on this device and has not yet reached your store; if the log shows the write failed before it was queued (see Troubleshoot step 2), re-enter it. If this persists, export diagnostics and contact WCPOS support. ## Troubleshoot[​](#troubleshoot "Direct link to Troubleshoot") 1. Do not assume this code will retry. Expand the log entry first: if it confirms the mutation was already queued, WCPOS retries automatically, so leave it open and let the queue drain. 2. If the error says the engine resident is missing or the write failed before a mutation ID was returned, nothing was queued — return to that record or order and save it again. 3. Expand the log entry and note the event code and any serverCode: a 999 code means the specific cause has no dedicated code yet, so this context is exactly what support needs. 4. If the code keeps appearing, use Copy debug info and contact support — reporting it is how the specific code gets added. ## Details[​](#details "Direct link to Details") * Code `SYNC999` (`SYNC_UNEXPECTED`) * Severity error * Introduced in WCPOS 1.10.0 --- # Extensions WCPOS supports extensions that add new functionality to your point of sale. The extension directory lets you browse available extensions, install them directly from the POS settings, and manage updates. Pro Feature Installing and managing extensions requires [WCPOS Pro](/getting-started/pro-license.md). The free version displays the extension catalog but disables install and activation controls. ## Available Extensions[​](#available-extensions "Direct link to Available Extensions") ### Payment Gateways[​](#payment-gateways "Direct link to Payment Gateways") Custom checkout gateways designed for in-person POS use. [Stripe TerminalIn-person card payments on Stripe Terminal hardware (S700, WisePOS E). Supports MOTO and simulator mode.](/payment/gateways/stripe-terminal.md) [SumUp TerminalAccept card payments through SumUp card readers.](/payment/gateways/sumup-terminal.md) [Vipps MobilePayPhone-based payments via QR code or push notification. Vipps (Norway), MobilePay (Denmark, Finland).](/payment/gateways/vipps-mobilepay.md) [Email InvoiceEmail the customer a payment link to settle the order online.](/payment/gateways/email-invoice.md) Want to build your own? Start from the [Gateway Template](/reference/gateway-template.md) — or see the [Custom Gateways overview](/payment/gateways/.md) for the full list. ### Multilingual[​](#multilingual "Direct link to Multilingual") Filter POS products by language so translated duplicates don't appear in cashier search and the catalog grid. [WCPOS PolylangPolylang integration — language-aware product sync and per-store language selection for WCPOS Pro.](/extensions/polylang.md) [WCPOS WPMLWPML integration — filter POS products to a single language.](/extensions/wpml.md) [WCPOS WP MultilangWP Multilang integration — filter POS products to a single language.](/extensions/wp-multilang.md) ### Coupons and Store Credit[​](#coupons-and-store-credit "Direct link to Coupons and Store Credit") [WCPOS StoreApps Smart CouponsRedeem StoreApps Smart Coupons store credit in WCPOS, with receipt balance labels and order-note audit history.](/extensions/storeapps-smart-coupons.md) ### Inventory[​](#inventory "Direct link to Inventory") [WCPOS ATUM IntegrationLink WCPOS Pro stores to ATUM Multi-Inventory locations for per-location stock, pricing, and SKUs.](/extensions/atum.md) ## Browsing Extensions[​](#browsing-extensions "Direct link to Browsing Extensions") Open the extension directory from `POS Settings > Extensions` (also labeled **Plugins** in some versions). The directory displays a card grid of available extensions. Each card shows: * **Icon** (or a puzzle-piece fallback if the extension doesn't provide one) * **Name and version** * **Description** * **Category badge** * **Status** — active, inactive, update available, or not installed ### Filtering and Search[​](#filtering-and-search "Direct link to Filtering and Search") Use the **category pill buttons** at the top to filter extensions by category. You can also use the **search field** to find extensions by name, description, or tags. ## Installing an Extension[​](#installing-an-extension "Direct link to Installing an Extension") 1. Open `POS Settings > Extensions`. 2. Find the extension you want and click **Install**. 3. The extension is downloaded and installed using the WordPress plugin installer. 4. Once installed, click **Activate** to enable it. Behind the scenes, WCPOS uses WordPress's native `Plugin_Upgrader` to handle installation, so extensions follow the same process as any WordPress plugin. ## Activating and Deactivating[​](#activating-and-deactivating "Direct link to Activating and Deactivating") Each installed extension has **Activate** and **Deactivate** buttons on its card. * **Activate** enables the extension so it can run in the POS. * **Deactivate** disables it without uninstalling. The extension files remain on your server and can be reactivated at any time. ## Updating Extensions[​](#updating-extensions "Direct link to Updating Extensions") When a newer version of an installed extension is available, the card shows an **Update Available** badge and an **Update** button. ### Auto-Updates[​](#auto-updates "Direct link to Auto-Updates") Extensions installed from the directory have **auto-update enabled by default**. You can toggle auto-updates on or off per extension from its card in the directory. When auto-update is on, WordPress will apply new versions automatically, just like it does for plugins with auto-update enabled. ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### "Requires Pro" Message on Buttons[​](#requires-pro-message-on-buttons "Direct link to \"Requires Pro\" Message on Buttons") The install, activate, and update buttons are disabled in the free version of WCPOS. Upgrade to [WCPOS Pro](/getting-started/pro-license.md) to manage extensions. ### Extension Fails to Install[​](#extension-fails-to-install "Direct link to Extension Fails to Install") * Check that your WordPress server has write permissions to the `wp-content/plugins` directory. * Verify that your server can make outbound HTTPS requests (some hosts block external downloads). * Look at the error details in `WP Admin > POS > Support > Logs`. ### Extension Not Appearing After Install[​](#extension-not-appearing-after-install "Direct link to Extension Not Appearing After Install") * Refresh the POS — the extension list is cached for up to 12 hours. * Confirm the extension is activated (installed but inactive extensions won't run). ### Catalog Not Loading[​](#catalog-not-loading "Direct link to Catalog Not Loading") The extension catalog is fetched from a remote source and cached locally for 12 hours. If the catalog doesn't load: * Check your server's internet connectivity. * Try again after the cache expires, or clear your server's transient cache. *** ## For Developers[​](#for-developers "Direct link to For Developers") ### Creating a POS Extension[​](#creating-a-pos-extension "Direct link to Creating a POS Extension") A WCPOS extension is a standard WordPress plugin that integrates with the POS through WCPOS hooks and APIs. To create one: 1. **Start with a WordPress plugin.** Your extension needs a standard plugin header and entry file, just like any WooCommerce or WordPress plugin. 2. **Integrate with WCPOS.** Use the hooks and filters provided by WCPOS to add functionality to the POS interface or backend. 3. **Host releases on GitHub.** The extension directory uses GitHub Releases to track versions and deliver updates. ### Submitting to the Directory[​](#submitting-to-the-directory "Direct link to Submitting to the Directory") The extension catalog is maintained in the [`wcpos/extensions`](https://github.com/wcpos/extensions) GitHub repository. To list your extension: 1. Review the catalog format and metadata requirements in the repository's README. 2. Open a pull request to add your extension's metadata to `catalog.json`. 3. Once merged, your extension will appear in the directory for all WCPOS Pro users. ### GitHub Release Conventions[​](#github-release-conventions "Direct link to GitHub Release Conventions") The update lifecycle relies on GitHub Releases: * **Tag versions** using semantic versioning (e.g., `v1.0.0`, `v1.2.3`). * **Attach the plugin zip** as a release asset — this is the file that gets downloaded when a user installs or updates. * **Publish the release** (not draft) so the directory can detect it. When you publish a new release, users with your extension installed will see the update available in their extension directory. If auto-update is enabled, it will be applied automatically. For full details on the catalog schema and submission process, see the [`wcpos/extensions`](https://github.com/wcpos/extensions) repository. --- # WCPOS ATUM Integration Integrates [ATUM Multi-Inventory](https://www.stockmanagementlabs.com/addons/atum-multi-inventory/) with [WCPOS Pro](/getting-started/pro-license.md), enabling location-based inventory, pricing, and SKUs at the Point of Sale. ATUM Multi-Inventory lets you split a product's stock across multiple inventory locations — warehouses, retail stores, and so on. This plugin connects those ATUM locations to WCPOS Pro [stores](/stores/.md) so each POS terminal sees the correct stock levels, prices, and SKUs for its physical location. ## Features[​](#features "Direct link to Features") #### Per-Location Stock Each store pulls stock quantities from its assigned ATUM inventory location rather than aggregate WooCommerce stock. #### Flexible Pricing Choose pricing from WooCommerce defaults, WCPOS Pro per-store prices, or ATUM location-specific prices. #### Location SKUs Optionally swap the product's main SKU for an ATUM location-specific SKU at the POS. #### Audit-Safe Stock Movement Orders deduct and restore stock at the correct ATUM location, with full audit trail in `atum_inventory_orders`. #### Product Edit Write-Back POS edits to stock, price, and SKU sync back to the mapped ATUM inventory row for that location. ## Installation[​](#installation "Direct link to Installation") 1 #### Install ATUM and Multi-Inventory Install [ATUM Inventory Management](https://wordpress.org/plugins/atum-stock-manager-for-woocommerce/) and the [ATUM Multi-Inventory add-on](https://www.stockmanagementlabs.com/addons/atum-multi-inventory/). Configure your inventory locations in ATUM. 2 #### Install WCPOS ATUM Integration Install from `WP Admin > POS > Settings > Extensions`, or download the latest release from the [GitHub releases page](https://github.com/wcpos/wcpos-atum/releases) and upload via `Plugins > Add New > Upload Plugin`. 3 #### Map stores to ATUM locations Go to `POS > Stores`, edit a store, and configure the **ATUM Inventory** sidebar section. Pick the inventory location the store should use, choose a pricing source, and optionally enable SKU overrides. ## Store Configuration[​](#store-configuration "Direct link to Store Configuration") The plugin adds an **ATUM Inventory** section to the WCPOS Pro store editor sidebar with three settings per store: * **Inventory Location** — which ATUM location this store pulls stock from. * **Pricing Source** — where product prices come from: * *Default* — standard WooCommerce prices * *WCPOS Pro* — per-store pricing set in WCPOS Pro * *ATUM* — location-specific prices from the ATUM inventory * **SKU Override** — optionally use location-specific SKUs from ATUM instead of the product's main SKU. ## POS Behavior[​](#pos-behavior "Direct link to POS Behavior") When a store has an ATUM location assigned, the product data served to the POS is automatically adjusted: * **Stock quantities** reflect the specific location's inventory, not the aggregate WooCommerce stock. * **Stock status** is recalculated based on the location's quantity. * **Prices** come from the configured pricing source. * **SKUs** are swapped to the ATUM location SKU if override is enabled. All adjustments happen transparently through the WCPOS REST API — no changes are needed on the POS app side. Product edits made from the POS are also written back to the mapped ATUM inventory row; see [Product Edit Write-Back](#product-edit-write-back) below. ## Stock Management[​](#stock-management "Direct link to Stock Management") For POS orders placed at stores with a mapped ATUM location, the plugin lets ATUM's native stock deduction flow handle the write — but steers it to the correct location: 1. **REST payload injection.** When the POS creates or updates an order, the plugin injects a `mi_inventories` entry onto each line item so ATUM knows which location to draw from. Without this, ATUM would fall back to the main inventory. 2. **Location-scoped inventory filter.** The plugin filters ATUM's candidate inventory list to only those linked to the store's mapped location term, ensuring the right one is picked on both reduction and restoration. ATUM itself performs the actual stock change on order and refund, writing rows to `atum_inventory_orders` with the real `order_id` — preserving ATUM's audit trail. ## Product Edit Write-Back[​](#product-edit-write-back "Direct link to Product Edit Write-Back") When a cashier or manager edits a product or variation from the POS, the changes sync back to the mapped ATUM inventory row for that store's location — not just the main WooCommerce product. This keeps each location's stock, price, and SKU in sync with ATUM without manual updates in `WP Admin`. The write-back is triggered on WCPOS product and variation REST updates (`POST`, `PUT`, `PATCH` to `/wcpos/v1/products/...`) that include a `store_id`. The plugin looks up the store's mapped ATUM location and updates only the inventory row for that location — other locations are untouched. ### What Syncs[​](#what-syncs "Direct link to What Syncs") The write-back respects each store's configuration so ATUM data only changes when the store actually owns that data: | Field | When it syncs | | -------------------------------------- | -------------------------------------------------------------------------------- | | **Stock quantity** | Always — every store with a mapped ATUM location keeps its location row in sync. | | **Regular price / Sale price / Price** | Only when the store's **Pricing Source** is set to *ATUM*. | | **SKU** | Only when **SKU Override** is enabled for the store. | If the store uses *Default* or *WCPOS Pro* pricing, ATUM price fields are left alone so ATUM continues to serve as a reference price rather than the source of truth. The same applies to SKUs when override is off. ### What Doesn't Trigger Write-Back[​](#what-doesnt-trigger-write-back "Direct link to What Doesn't Trigger Write-Back") * Product creation (only updates write back — new products fall through to WooCommerce's normal save path). * Requests without a `store_id` — the POS has to tell the plugin which location to write to. * Stores without a mapped ATUM location. * Products without an existing ATUM inventory row for the store's location — the plugin will not create new inventory rows, only update existing ones. ## Requirements[​](#requirements "Direct link to Requirements") WordPress : WordPress 5.9+ with PHP 7.4+ WooCommerce : WooCommerce installed and activated ATUM : ATUM Inventory Management and ATUM Multi-Inventory add-on WCPOS : WCPOS Pro — multi-store is a Pro feature ## Related[​](#related "Direct link to Related") * [Multi-Store](/stores/.md) — per-store pricing, addresses, and cashier assignment * Source: [github.com/wcpos/wcpos-atum](https://github.com/wcpos/wcpos-atum) --- # WCPOS Polylang Adds [Polylang](https://polylang.pro/) awareness to WCPOS so the POS only shows products for a single language — no duplicated translations in product search, the catalog grid, or cashier workflows. WCPOS Pro stores can pin a per-store language; free installs fall back to the Polylang default language. ## What It Does[​](#what-it-does "Direct link to What It Does") * Filters WCPOS product and variation REST queries by language. * Intercepts WCPOS **fast-sync** routes (the lightweight `posts_per_page=-1` + `fields` requests the POS uses to refresh its local index) so translated duplicates never reach the client. * On free installs, applies the Polylang default language. * On Pro installs, each store can choose its own language from a new **Language** section in the store editor. * Respects WCPOS **POS-only** product visibility when building the fast-sync payload. The integration no-ops cleanly when Polylang is not active — you can install the plugin ahead of enabling Polylang without errors. ## Installation[​](#installation "Direct link to Installation") 1 #### Install Polylang Install [Polylang](https://wordpress.org/plugins/polylang/) (or Polylang Pro) and configure your site languages as normal. Make sure at least one language is set as the default. 2 #### Install WCPOS Polylang Install from the WCPOS extensions directory at `WP Admin > POS > Settings > Extensions`, or download the latest release from the [GitHub releases page](https://github.com/wcpos/wcpos-polylang/releases) and upload via `Plugins > Add New > Upload Plugin`. 3 #### (Pro) Set a per-store language If you run [multiple stores](/stores/.md) on WCPOS Pro, go to `POS > Stores`, edit a store, and pick its language from the **Language** sidebar section. Leave it at *Default* to use your Polylang default language. ## Per-Store Language (Pro)[​](#per-store-language-pro "Direct link to Per-Store Language (Pro)") On WCPOS Pro, the plugin adds a **Language** section to the store editor sidebar. Each store can be pinned to a single Polylang language slug — products served to that store are filtered to that language only. Stores left on *Default* use the Polylang default language. The per-store value is saved against the store post as `_wcpos_polylang_language` meta and is exposed via the WCPOS Pro stores REST API (`/wcpos/v1/stores`), so it round-trips through the POS like any other store setting. ## Compatibility Notes[​](#compatibility-notes "Direct link to Compatibility Notes") * **POS-only products:** when POS-only mode is enabled in WCPOS settings, online-only product IDs are excluded from the fast-sync payload so they do not leak into the POS. * **Free installs:** there is no UI for changing the language per store — the plugin uses Polylang's default language. If you need per-store languages, upgrade to [WCPOS Pro](/getting-started/pro-license.md). * **Plugin unavailable:** if Polylang is deactivated, the plugin silently does nothing. It will not throw errors or block the POS. ## Developer Hooks[​](#developer-hooks "Direct link to Developer Hooks") For advanced use, the plugin exposes a few filters: | Filter | Purpose | | ---------------------------------- | ----------------------------------------------------------------------------------------------------- | | `wcpos_polylang_resolved_language` | Override the language used for a given request. Receives the resolved slug and the `WP_REST_Request`. | | `wcpos_polylang_default_language` | Override the fallback language when no per-store value is set. | | `wcpos_polylang_is_supported` | Force the plugin on or off regardless of Polylang detection. | | `wcpos_polylang_minimum_version` | Require a minimum Polylang version (default: no version gate). | ## Requirements[​](#requirements "Direct link to Requirements") WooCommerce : WooCommerce installed and activated Polylang : Polylang (free or Pro) with at least one language configured WCPOS : Free version works; per-store language selection requires WCPOS Pro ## Related[​](#related "Direct link to Related") * [WCPOS WPML](/extensions/wpml.md) * [WCPOS WP Multilang](/extensions/wp-multilang.md) * [Multi-Store](/stores/.md) * Source: [github.com/wcpos/wcpos-polylang](https://github.com/wcpos/wcpos-polylang) --- # WCPOS StoreApps Smart Coupons Adds WCPOS compatibility for store credit created with [Smart Coupons by StoreApps / WooCommerce.com](https://woocommerce.com/products/smart-coupons/). It lets POS orders redeem StoreApps store credit, keeps the StoreApps balance in sync, and leaves an order-note audit trail for staff. This extension is specifically for the StoreApps / WooCommerce.com Smart Coupons plugin. Other plugins with similar “Smart Coupons” names are separate products and may need separate integrations. Pro Feature Installing and managing extensions from the directory requires [WCPOS Pro](/getting-started/pro-license.md). ## What It Does[​](#what-it-does "Direct link to What It Does") * Records the StoreApps `smart_coupons_contribution` metadata for POS-created orders when the normal checkout cart context is not available. * Lets StoreApps deduct the correct partial store-credit amount from the coupon balance after POS checkout. * Restores the StoreApps store-credit balance when the POS order is cancelled or refunded through WooCommerce's normal order lifecycle. * Adds a private order note after redemption showing the coupon code, amount used, and current balance. * Shows the remaining store-credit balance in the existing receipt discount row by appending it to the coupon description/discount label. The extension uses normal WooCommerce coupon fields and metadata. It does not add custom WCPOS coupon response fields or require custom receipt templates. ## Installation[​](#installation "Direct link to Installation") 1 #### Install StoreApps Smart Coupons Install and activate [Smart Coupons by StoreApps / WooCommerce.com](https://woocommerce.com/products/smart-coupons/). Create your store-credit coupons or gift cards as usual in WooCommerce. 2 #### Install WCPOS StoreApps Smart Coupons Install from `WP Admin > POS > Settings > Extensions`, or download the latest release from the [GitHub releases page](https://github.com/wcpos/wcpos-storeapps-smart-coupons/releases) and upload via `Plugins > Add New > Upload Plugin`. 3 #### Sync coupons to the POS Open the POS and sync coupons. Cashiers can then apply StoreApps store-credit coupons from the normal **Add Coupon** flow. ## Receipt Output[​](#receipt-output "Direct link to Receipt Output") WCPOS receipt templates already print coupon discounts using the discount row label. During receipt rendering, this extension appends the current StoreApps balance to that existing label. For example, a coupon description of **Gift card** may print as: ``` Gift card — Store credit balance: £61.50 ``` If the coupon has no description, the balance text is used as the discount label. Existing receipt templates do not need to be changed. ## Order Audit Trail[​](#order-audit-trail "Direct link to Order Audit Trail") After StoreApps processes a POS store-credit redemption, the extension adds a private order note similar to: ``` StoreApps Smart Coupons store credit recorded for WCPOS: Coupon STORE100 used £38.50. Current balance: £61.50. ``` Use this note to confirm which store-credit coupon was used, how much was redeemed, and what balance remained after the sale. ## Compatibility Notes[​](#compatibility-notes "Direct link to Compatibility Notes") * **StoreApps only:** this extension targets StoreApps / WooCommerce.com Smart Coupons. It does not target WebToffee or other smart-coupon plugins. * **Coupon data:** WCPOS continues to use normal WooCommerce coupon responses. StoreApps-specific state remains in WooCommerce metadata such as `smart_coupons_contribution` and coupon balance fields. * **Receipts:** balance text is added through the existing coupon description/discount label path, not by changing receipt data or templates. * **Inactive StoreApps plugin:** if StoreApps Smart Coupons is not active, the extension does nothing. ## Requirements[​](#requirements "Direct link to Requirements") WooCommerce : WooCommerce installed and activated Smart Coupons : Smart Coupons by StoreApps / WooCommerce.com WCPOS : WCPOS with coupon support; extension installation from the directory requires WCPOS Pro ## Related[​](#related "Direct link to Related") * [Coupons](/coupons/.md) * [Applying Coupons at the Till](/coupons/applying-coupons.md) * [Receipt Data](/receipts/receipt-data.md) * Source: [github.com/wcpos/wcpos-storeapps-smart-coupons](https://github.com/wcpos/wcpos-storeapps-smart-coupons) --- # WCPOS WP Multilang Integrates [WP Multilang](https://wordpress.org/plugins/wp-multilang/) with WCPOS so the POS only serves products for a single language. Unlike Polylang or WPML, WP Multilang stores all translations inside the same post — this plugin makes sure WCPOS reads the correct translation and doesn't duplicate entries in search results. ## What It Does[​](#what-it-does "Direct link to What It Does") * Filters WCPOS product and variation REST responses to a single WP Multilang language. * Intercepts WCPOS **fast-sync** routes so only the active language's content reaches the client. * Free installs use the WP Multilang default language. * Pro installs can pin a language per store from the store editor. ## Installation[​](#installation "Direct link to Installation") 1 #### Install WP Multilang Install [WP Multilang](https://wordpress.org/plugins/wp-multilang/) and configure your site languages, with at least one language set as the default. 2 #### Install WCPOS WP Multilang Install from `WP Admin > POS > Settings > Extensions`, or download the latest release from the [GitHub releases page](https://github.com/wcpos/wcpos-wp-multilang/releases) and upload via `Plugins > Add New > Upload Plugin`. 3 #### (Pro) Pin a language per store On WCPOS Pro, edit a store under `POS > Stores` and pick its language from the **Language** sidebar section. Leave at *Default* to use the WP Multilang default language. ## Requirements[​](#requirements "Direct link to Requirements") WooCommerce : WooCommerce installed and activated WP Multilang : WP Multilang with at least one language configured WCPOS : Free version works; per-store language selection requires WCPOS Pro ## Related[​](#related "Direct link to Related") * [WCPOS Polylang](/extensions/polylang.md) * [WCPOS WPML](/extensions/wpml.md) * [Multi-Store](/stores/.md) * Source: [github.com/wcpos/wcpos-wp-multilang](https://github.com/wcpos/wcpos-wp-multilang) --- # WCPOS WPML Integrates [WPML](https://wpml.org/) with WCPOS so the POS only serves products for a single language — translated duplicates stop appearing in product search and the catalog grid. On WCPOS Pro, you can pin a language per store. ## What It Does[​](#what-it-does "Direct link to What It Does") * Filters WCPOS product and variation REST queries to a single WPML language. * Intercepts WCPOS **fast-sync** routes (the lightweight requests the POS uses to refresh its local index) so translated duplicates never reach the client. * Free installs use the WPML default language. * Pro installs can override the language per store from the store editor. ## Installation[​](#installation "Direct link to Installation") 1 #### Install WPML Install and configure [WPML](https://wpml.org/) as normal with at least one language set as the default. 2 #### Install WCPOS WPML Install from `WP Admin > POS > Settings > Extensions`, or download the latest release from the [GitHub releases page](https://github.com/wcpos/wcpos-wpml/releases) and upload via `Plugins > Add New > Upload Plugin`. 3 #### (Pro) Pin a language per store On WCPOS Pro, edit a store under `POS > Stores` and pick its language from the **Language** sidebar section. Leave at *Default* to use the WPML default language. ## Known WPML Compatibility Issues[​](#known-wpml-compatibility-issues "Direct link to Known WPML Compatibility Issues") These are behaviours of WPML itself rather than the integration — worth knowing before rolling out multilingual in production: * **POS custom fields don't carry across translations.** WPML translates products but does not copy WCPOS custom fields to translated versions by default. A product marked "POS Only" in the default language may lose that setting on its translations. Configure WPML to copy WCPOS custom fields during translation. * **POS-only products and 404s on the storefront.** Because WPML generates storefront pages for each language, POS-only products may render as 404s when accessed on the website. This is a known WPML interaction, not a WCPOS bug. See [POS-Only Products](/products/pos-only-products.md) for the related POS visibility controls. ## Requirements[​](#requirements "Direct link to Requirements") WooCommerce : WooCommerce installed and activated WPML : WPML with at least one language configured WCPOS : Free version works; per-store language selection requires WCPOS Pro ## Related[​](#related "Direct link to Related") * [WCPOS Polylang](/extensions/polylang.md) * [WCPOS WP Multilang](/extensions/wp-multilang.md) * [Multi-Store](/stores/.md) * Source: [github.com/wcpos/wcpos-wpml](https://github.com/wcpos/wcpos-wpml) --- # Connecting to Your Store Desktop & Mobile Only This screen is only shown in the Desktop and Mobile apps. Web users access the POS directly at `yourdomain.com/pos` and log in with their WordPress credentials. ## Connect Screen Overview[​](#connect-screen-overview "Direct link to Connect Screen Overview") When you open the WCPOS Desktop or Mobile app, you'll see the Connect screen. This is where you manage your store connections and user logins. ## Adding a New Store[​](#adding-a-new-store "Direct link to Adding a New Store") 1. Enter your WooCommerce store URL in the text field (e.g., `https://mystore.com`) 2. Click **Connect** 3. You'll be redirected to log in with your WordPress credentials 4. After successful login, you'll be returned to the app ## Multiple Stores[​](#multiple-stores "Direct link to Multiple Stores") You can connect to as many WooCommerce stores as you need. Each store appears as a separate card on the Connect screen, showing: * **Store name** and favicon * **Store URL** * **Logged in users** for that store This is useful if you manage multiple locations or businesses. ## Multiple Users Per Store[​](#multiple-users-per-store "Direct link to Multiple Users Per Store") Each store can have multiple users logged in simultaneously. This is helpful for: * **Shift changes** - New cashier can log in before the previous one logs out * **Multi-register setups** - Different cashiers on different devices * **Quick switching** - Easily switch between user accounts ### Adding a User[​](#adding-a-user "Direct link to Adding a User") Click the button next to "Logged in users" to add another user to that store. ### Switching Users[​](#switching-users "Direct link to Switching Users") Click on a user badge (e.g., "Brenda") to open the POS as that user. ### Removing a User[​](#removing-a-user "Direct link to Removing a User") Click the **×** on a user badge to log that user out of the store. ## Removing a Store[​](#removing-a-store "Direct link to Removing a Store") Click the red **×** button on the store card to remove it from your list. This logs out all users and removes the store connection from the app. ## Demo Store[​](#demo-store "Direct link to Demo Store") At the bottom of the screen, you may see an "Enter Demo Store" link. This connects you to a demo WooCommerce store to try out WCPOS features without affecting your own store data. ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") First thing to check: `X-Frame-Options` The desktop and mobile apps use **iframes** for login, payment, and receipts. **Any** server header or plugin that sends `X-Frame-Options: DENY` or `SAMEORIGIN` will break login. This is the single most common cause of app login failures — check the login page's response headers (browser dev tools, or `curl -I https://yourstore.com/wp-login.php`) before anything else. Can't connect to my store? * Ensure the WCPOS plugin is installed and activated on your WordPress site * Check that you're using the correct URL (include `https://` — the WooCommerce REST API requires SSL) * Try opening `yourdomain.com/pos` in a web browser first to confirm the plugin works * Verify that the WooCommerce REST API is accessible * Check that your user account has POS access permissions Login fails in the desktop or mobile app Most app login failures are caused by a security or caching plugin blocking the login iframe: * **`X-Frame-Options` headers** (set by a security plugin or your server) block the login iframe — see the note above. Temporarily disable the security plugin, log in, then re-enable it (your session lasts about a week). * **Security plugins** — Wordfence, Really Simple Security, WPS Hide Login, iThemes/Solid Security, and Defender Pro are common culprits. See the full list and fixes in [Plugin Conflicts](/support/troubleshooting/plugin-conflicts.md#security-and-login-plugins). * **Wordfence 2FA** — the 2FA code field doesn't render in the login iframe. Disable 2FA for POS users for now. * **Custom login URL** (e.g. WPS Hide Login) — the app can't find the login page. Use the standard `/wp-admin/` URL. * **Caching plugins** can keep serving the blocked login form even after you disable the offending plugin — clear the cache, or clear the app cache / reinstall the desktop app. "REST API requires authentication" or a security-plugin error on the connect screen A plugin (e.g. Force Login or a JWT auth plugin) is requiring authentication for all REST API requests, so the app can't read your site's public info. The app now shows the server's actual message (e.g. *"Only authenticated users can access the REST API"*) instead of misreporting the site type. **Fix:** configure the security plugin to allow unauthenticated access to `/wp-json/wcpos/` and `/wp-json/wc/v3/`, or disable it just long enough to complete the first connection. "Does not appear to be a WordPress site" (desktop app) The desktop app discovers the REST API via the HTTP `Link` header. If a plugin (commonly **Image Prioritizer** or other performance plugins) floods or truncates that header, discovery fails. **Fix:** disable image-optimisation / header-modifying performance plugins and retry. The app says it needs an update / crashes after an update Check for a version mismatch between the app and the server plugin — the app store may have pushed an app update while the WCPOS plugin still needs updating (or vice-versa). For v1.10, the app and the WCPOS plugin must both be on the **v1.10 release line** because the app uses the plugin's v2 sync API. If only one side was updated and requests fail with `rest_no_route`, update the other half. "Cannot create fast store database" error This is a race condition on first login. **Close the app completely and try again** — it usually succeeds on the second attempt. Stuck on the user-selection screen (desktop app) After logging in you see your username but no obvious way forward. **Click your username/name** to proceed into the POS — the name itself is the button. Connection keeps failing? * Try accessing `yourdomain.com/pos` in a web browser first to verify the plugin is working * Check your site's error logs for any issues * Confirm your host isn't blocking the REST API — see [Hosting-Specific Notes](/support/performance/server.md#hosting-specific-notes) * Ensure your server meets the [minimum requirements](/support/performance/server.md#minimum-server-requirements) --- # Free vs Pro WCPOS comes in two editions. The **free plugin** is everything you need to take payments at the counter, print receipts, and sync orders back to WooCommerce. **Pro** adds the management screens (Products, Orders, Customers, Reports), more payment gateways, coupons, refunds, and multi-store support. If you mainly need a till that records sales, the free plugin is enough. If you also want to run the day-to-day of your store from the POS — manage stock, look up old orders, refund a customer, accept card payments through an integrated reader — that's what Pro is for. ## At a glance[​](#at-a-glance "Direct link to At a glance") | Area | Free | Pro | | -------------------------------------------------------- | ---- | --- | | Take sales and print/email receipts | | | | Cash and external-card payments | | | | Integrated card readers (Stripe, SumUp, Vipps/MobilePay) | | | | Coupons at the register | | | | Refunds from the POS | | | | Edit stock, prices, and product details from the POS | | | | Look up and reprint historical orders | | | | Add and edit customers | | | | End-of-day reports | | | | Multiple store locations | | | | Per-store receipt templates, tax IDs, and branding | | | | Install and manage POS extensions from settings | | | | Priority Discord support | | | ## What's in the free plugin[​](#whats-in-the-free-plugin "Direct link to What's in the free plugin") The free plugin from [WordPress.org](https://wordpress.org/plugins/woocommerce-pos/) covers the core "ring up a sale" workflow. #### Cash + Card checkout Two built-in payment methods: **Cash** with change calculation, and **Card** for when you take payment on an external terminal and just need to record the sale. #### Cart and product search Search the product panel, scan barcodes, add line items, apply line-item discounts, and add open-priced "Misc" items not in your catalogue. #### Receipts and thermal printing Choose from a built-in [template gallery](/receipts/customise.md) — receipts, invoices, quotes, packing slips, gift receipts, kitchen tickets — and print to 58 mm or 80 mm thermal printers over network, Bluetooth, or USB. #### Offline storage + sync Products and orders are stored locally so the till stays fast and works through a flaky connection. Orders sync back to WooCommerce when the network returns. #### Barcode support Scan products straight into the cart with a USB or Bluetooth scanner, or use the device camera. #### Customer Tax IDs Built-in Tax ID field on the customer record — VAT, ABN, GST, GSTIN, EIN, and other regional formats. #### Cross-platform + multilingual Browser, desktop (Windows/macOS), and mobile apps (iOS/Android, beta). Translated into the major European, Asian, and Latin American languages. POS-only customer/coupon access on Free On the free plugin you can still **select** an existing customer or **see** the Coupons catalogue at the till — you just can't add/edit customers, and you can't apply coupon codes at checkout. Those become available with Pro. ## What Pro adds[​](#what-pro-adds "Direct link to What Pro adds") Pro unlocks the rest of the back-office, more payment options, and per-store features. Every item below is Pro-only. ### Management screens[​](#management-screens "Direct link to Management screens") The free plugin gives you a Product Panel for ringing up sales. Pro adds the full management surface: | Screen | What you can do | | ------------------------------- | ------------------------------------------------------------------------------------------------------------ | | **[Products](/products/.md)** | Edit stock levels, prices, and cost of goods sold inline. Bulk operations across the catalogue. | | **[Orders](/orders/.md)** | Look up historical orders, reprint receipts, edit orders, and access the refund flow. | | **[Customers](/customers/.md)** | Add new customers and edit existing customer details (free users can only select from a picker at checkout). | | **[Reports](/reports/.md)** | End-of-day sales reports — totals by payment method, cashier, and store, suitable for cash reconciliation. | | **[Coupons](/coupons/.md)** | Browse the WooCommerce coupon catalogue from the till (free users see a blurred preview only). | ### Payment gateways[​](#payment-gateways "Direct link to Payment gateways") The free plugin's "Card" gateway just records a sale that you took on an external terminal — there's no integration with the reader itself. Pro lets you use **any WooCommerce payment gateway** at the POS, and bundles several integrated gateways: | Gateway | Use case | | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | **[Stripe Terminal](/payment/gateways/stripe-terminal.md)** | Direct integration with Stripe's S700 / WisePOS E readers. Supports MOTO (phone orders) and a simulator for testing. | | **[SumUp Terminal](/payment/gateways/sumup-terminal.md)** | Pair a SumUp card reader to the POS and complete card payments without leaving the till. | | **[Vipps MobilePay](/payment/gateways/vipps-mobilepay.md)** | Phone-based payments via QR code or push notification — Vipps in Norway, MobilePay in Denmark and Finland. | | **[Email Invoice](/payment/gateways/email-invoice.md)** | Send the customer a payment link by email; the order completes when they pay online. | | **[Web Checkout](/payment/gateways/web-checkout.md)** | Redirect the customer to your hosted checkout to complete payment online. | | **Any other WooCommerce gateway** | Use the [Gateway Template](/payment/gateways/.md) to wrap any WooCommerce payment plugin for POS checkout. | ### Coupons, refunds, and the at-counter workflow[​](#coupons-refunds-and-the-at-counter-workflow "Direct link to Coupons, refunds, and the at-counter workflow") #### Coupons at the register Search and apply WooCommerce coupon codes at checkout. Coupons appear as removable pills in the cart, support sequential discounts, and respect all the usual rules — expiry, usage limits, min/max spend, product and category restrictions. #### Refunds at the till Issue full or partial [refunds](/orders/refunds.md) from the POS — refund to the original payment method or as cash. Cashier and store are recorded on the refund for a full audit trail. ### Multi-store, stock, and branding[​](#multi-store-stock-and-branding "Direct link to Multi-store, stock, and branding") #### Multi-store locations Create multiple [store locations](/stores/.md), each with its own address, logo, tax rates, [tax IDs](/settings/wp-admin/store-tax-ids.md), and cashier assignments. Orders and reports can be filtered per store. #### Per-location inventory (ATUM) Link Pro stores to [ATUM Multi-Inventory](/extensions/atum.md) locations for per-location stock, pricing, and SKUs. #### Per-store receipt templates Assign different receipt and invoice [templates](/receipts/.md) to different stores. Each store has its own branding — logo, address, contact details — and template ordering. #### Install POS extensions Install, activate, and update POS [extensions](/extensions/.md) and integrations directly from the settings screen. Free users see the catalogue but the install controls are disabled. ### Support[​](#support "Direct link to Support") * **Priority Discord support** — one-on-one assistance via a private channel, in addition to the public community channels. ## Pricing[​](#pricing "Direct link to Pricing") Pro is sold per site from [wcpos.com/pro](https://wcpos.com/pro): * **Annual licence** — $129 / year, includes updates and support for the licence term. * **Lifetime licence** — $399 one-time, includes updates and support for the lifetime of the product. Prices current as of May 2026; subject to change. When a licence expires, Pro features keep working but you stop receiving updates and support. See [Installing WCPOS Pro](/getting-started/pro-license.md) for activation steps and licence troubleshooting. Still deciding? You can try the public demo at [demo.wcpos.com/pos](https://demo.wcpos.com/pos) (login `demo` / `demo`) — it runs the full Pro feature set so you can see the management screens, coupons, and refund flow before buying. ## Ready to upgrade?[​](#ready-to-upgrade "Direct link to Ready to upgrade?") Head over to [Installing WCPOS Pro](/getting-started/pro-license.md) for download and activation steps. * **v1.8+ Pro** — deactivate and delete the free plugin first. From v1.8 onwards, Pro is a standalone plugin that should not be installed alongside the free version. * **Older Pro (< v1.8)** — keep the free plugin installed if your Pro version requires it. --- # Installation Requirements To ensure proper functionality and optimal performance of the WCPOS plugin, please make sure your environment meets the following minimum requirements: ## Server Requirements[​](#server-requirements "Direct link to Server Requirements") The WCPOS plugin runs on your WordPress site, which must meet these minimums: | Component | Minimum version | Notes | | ----------- | --------------- | --------------- | | WordPress | 5.6 | — | | WooCommerce | 5.3 | — | | PHP | 7.4 | 8.x recommended | Meeting these minimums ensures compatibility and stability with your WordPress environment, and access to the latest WCPOS features. ## Browser Requirements[​](#browser-requirements "Direct link to Browser Requirements") The web version of the POS runs in any modern browser. Use the latest stable release: | Browser | Supported version | | --------------- | ----------------- | | Google Chrome | Latest stable | | Mozilla Firefox | Latest stable | | Safari | Latest stable | | Microsoft Edge | Latest stable | Avoid private / incognito mode Private browsing can block access to the browser's local storage, which WCPOS uses to store data offline — some features will not work correctly. JavaScript must also be enabled. ## App Requirements[​](#app-requirements "Direct link to App Requirements") WCPOS is also available as a desktop and mobile app. Each is built for the following minimum operating systems: | Platform | Minimum OS | Architectures | | --------------- | ------------------------- | -------------------------- | | Windows desktop | Windows 10 | x64, ARM64 | | macOS desktop | macOS 12 (Monterey) | Intel (x64), Apple Silicon | | iOS / iPadOS | iOS 16.4 | — | | Android | Android 10 (API level 29) | — | Printing permissions Bluetooth and network printing require granting the app the relevant Bluetooth and local network permissions when prompted. ## Installing the Plugin[​](#installing-the-plugin "Direct link to Installing the Plugin") 1. Go to `WP Admin > Plugins > Add Plugin` 2. Search for "wcpos" 3. Click **Install Now**, then **Activate** Alternatively, you can download the plugin from [WordPress.org](https://wordpress.org/plugins/woocommerce-pos/) and upload it manually. ## Accessing the POS[​](#accessing-the-pos "Direct link to Accessing the POS") After activation, you can access the POS at: * **Web:** `yourdomain.com/pos` * **Desktop:** [Windows](https://updates.wcpos.com/electron/download/win32-x64), [Mac (Intel)](https://updates.wcpos.com/electron/download/darwin-x64), [Mac (Apple Silicon)](https://updates.wcpos.com/electron/download/darwin-arm64) * **Mobile:** [iOS](https://testflight.apple.com/join/JGBdVRrW), [Android](https://play.google.com/apps/testing/com.wcpos.main) By meeting the minimum requirements and using a compatible web browser, you can have a seamless experience using the WCPOS plugin and leverage its full potential to manage your point of sale operations efficiently. If you have any further questions or need assistance, please don't hesitate to reach out to our support team by posting them to the [Discord chat](https://wcpos.com/discord) or emailing them to . --- # Offline Functionality WCPOS stores your product and customer data in a local database on each device. This means parts of the POS work without an internet connection, while others require connectivity. ## What Works Offline[​](#what-works-offline "Direct link to What Works Offline") * **Browsing products** — search, filter, and view product details from local data * **Browsing customers** — look up customer names, emails, and addresses * **Building a cart** — add items, change quantities, edit prices, and apply POS discounts * **Applying coupons** (Pro) — codes validate locally against synced coupon data; the server re-validates when the queued order reaches it * **Saving an order** — hold or save an order to the device; it joins the outbound queue and lands in WooCommerce when the connection returns * **Barcode scanning** — scan barcodes to find products in the local database * **Viewing reports** — the default (offline) report type generates reports from locally stored orders ## What Requires a Connection[​](#what-requires-a-connection "Direct link to What Requires a Connection") * **Taking payment** — completing checkout renders a payment page hosted by your server, so the payment step itself can't be finished offline. You can still build and **save** the order while offline, then take payment once you're back online. * **Server-dependent checkout actions** — Web Checkout, integrated online or terminal gateways, and **Save to Server** need their respective services to be reachable * **Syncing data** — pulling new products, updated prices, or new customers from WooCommerce * **Logging in** — initial authentication requires a connection to your WordPress site * **Licence activation** — Pro licence checks need to reach the WCPOS licence server * **Processing refunds** — refunds can't be queued offline; the gateway and your store both need to be reachable (see [Refunds](/orders/refunds.md)) Completing a sale needs a connection You can build and **save** an order offline, but the payment step itself waits for a connection. Being able to *complete* a sale offline — starting with cash — is on the [roadmap](/getting-started/roadmap.md). ## How the Local Database Works[​](#how-the-local-database-works "Direct link to How the Local Database Works") When you first open WCPOS, it seeds your product catalogue in the background and pulls other data as you use it — you can start selling as soon as the first products are on the device. From then on, a background change check (every 60 seconds by default, tunable in [Store health](/support/store-health.md)) fetches only what changed on the server. The local database: * **Persists between sessions** — data survives browser restarts and device reboots * **Is per device (and per cashier)** — each device keeps its own local copy; cashiers don't share local data * **Stays in sync** — background change checks pull updates; your changes queue locally and push to the server You can see exactly what's on the device — and what's still waiting to send — in **Store health → Database**. For more technical detail, see [How the Sync Engine Works](/reference/sync-engine.md). ## Changes You Make Offline Are Queued[​](#offline-writes "Direct link to Changes You Make Offline Are Queued") Every change you make in the POS — a saved order, a new or edited customer, a coupon, a stock or price edit (Pro), a receipt email — is saved to the device first and queued to send. While you're offline the queue simply waits; nothing is lost by losing connectivity mid-shift. The queue is durable across restarts and crashes too: if the app hits an error screen, choosing **Try again** reloads it without discarding sales that haven't been sent yet. When the connection returns, the queue drains automatically. If your server refuses a change outright (rare — for example, a record the server considers invalid), the POS won't retry it silently forever: the change is parked in **Store health → Database** under *"changes never reached your server"*, with the server's reason and explicit **Send again** / **Discard** actions. See [Store Health](/support/store-health.md#refused-changes). ## Connectivity Indicator[​](#connectivity-indicator "Direct link to Connectivity Indicator") The POS header shows a coloured dot indicating connection status: * **Green** — connected to the server, all features available * **Yellow** — intermittent connection, some operations may be slow * **Red** — offline, limited to local data ## What Happens During Connectivity Loss[​](#what-happens-during-connectivity-loss "Direct link to What Happens During Connectivity Loss") If you lose your internet connection while using the POS: 1. **Products and customers remain browsable** from local data. 2. **You can continue building carts** and editing items — every change queues locally. 3. **You can build and save orders, but not take payment** — carts and edits queue locally, and an order can be saved to send later. Completing payment waits until the connection returns, because checkout is rendered by your server. 4. **Open orders are preserved** in the local database until connectivity returns. ## When Connection Restores[​](#when-connection-restores "Direct link to When Connection Restores") Once your connection comes back: * The connectivity indicator turns green. * **Queued changes drain to your server automatically** — sales and edits made while offline push without any manual action. * Server-dependent payment gateways and **Save to Server** become available again. * Background sync resumes, pulling any product or customer changes that happened while you were offline. ## Tips for Unreliable Connections[​](#tips-for-unreliable-connections "Direct link to Tips for Unreliable Connections") * **Use "Save to Server" on important orders** — this pushes the order to WooCommerce immediately, so it's not lost if the device's local database is cleared. * **Check Store health after an outage** — the *changes waiting to send* tile in **Store health → Database** confirms when everything has reached your server. * **Sync while you have signal** — if you know connectivity will be intermittent, let the catalogue seed finish while you have a good connection. --- # Re-Installing a Previous Version of the WCPOS Plugin ## Re-Installing a Previous Version[​](#re-installing-a-previous-version "Direct link to Re-Installing a Previous Version") If you need to revert to a previous version of the WCPOS plugin, follow these steps: 1. Visit the WordPress.org page [Advanced View](https://wordpress.org/plugins/woocommerce-pos/advanced/) for WCPOS. 2. Scroll down to the **Advanced Options** section and locate **Previous Versions** select menu. 3. Open the select menu and you will see a list of available plugin versions. Find the version you want to install and click on the **Download** button next to it. Save the downloaded file to your desktop or a convenient location. ![Advanced Options](https://wcpos.com/wp-content/uploads/2023/06/advanced-options.png) [](https://wordpress.org/plugins/woocommerce-pos/advanced/) [Advanced View](https://wordpress.org/plugins/woocommerce-pos/advanced/) for WCPOS 4. Log in to your WordPress Admin dashboard. 5. Navigate to the **Plugins** page by clicking on **Plugins** in the left-hand menu. 6. Deactivate and delete the current version of the WCPOS plugin. This will remove the plugin from your WordPress installation. Don't worry, your data will not be lost. 7. Click on the **Add Plugin** button at the top of the page. 8. On the **Add Plugins** page, click on the **Upload Plugin** button. 9. Choose the previously downloaded plugin file from your desktop or the location where you saved it. ![Upload Plugin](https://wcpos.com/wp-content/uploads/2023/06/upload-plugin.png) Upload plugin in the WordPress Admin 10. Click on the **Install Now** button and wait for the installation to complete. 11. After the installation is finished, click on the **Activate** button to activate the previous version of the WCPOS plugin. That's it! You have successfully re-installed a previous version of the WCPOS plugin. If you encounter any issues during the re-installation process or need further assistance, please contact our support team at . --- # Installing WCPOS Pro Pro Feature [WCPOS Pro](https://wcpos.com/pro) is a paid plugin that powers the management screens, additional payment gateways, and other Pro-only features in WCPOS. **As of v1.8+, Pro is a standalone plugin** — you do not need the free [WCPOS plugin](https://wordpress.org/plugins/woocommerce-pos/) installed alongside it. ## What's Included in Pro?[​](#whats-included-in-pro "Direct link to What's Included in Pro?") WCPOS Pro unlocks additional features: * **Products Screen** - Edit stock levels and prices directly in the POS * **Orders Screen** - View and manage order history * **Customers Screen** - Add and edit customer information * **Reports Screen** - Generate end-of-day sales reports * **Additional Payment Gateways** - Stripe Terminal, SumUp, and custom gateways ## Installation[​](#installation "Direct link to Installation") If you have purchased a license for WCPOS Pro please follow the steps below to install and activate the plugin: Upgrading from older versions? If you previously had both the free WCPOS plugin and an older Pro add-on installed, **deactivate and delete the free plugin** before activating the new standalone Pro plugin. Running both side-by-side can cause activation errors such as *"Invalid response fetching remote state"* or fatal *"Class not found"* errors. 1. Go to: 2. Under **Downloads**, click the download link and save the plugin to your desktop. 3. Then go to your site, login and go to `WP Admin > Plugins > Add Plugin > Upload Plugin` 4. Upload the plugin zip file from your desktop and activate. 5. Next, go to `WP Admin > POS > Settings > License` and enter your License Key and License Email to complete the activation. ![My Downloads](https://wcpos.com/wp-content/uploads/2014/07/my-download.png "You can download WCPOS Pro on your account page") ## Updates[​](#updates "Direct link to Updates") When new versions are ready they will appear in your Updates dashboard like any other plugin. You can also download the latest version from your [account page](https://wcpos.com/my-account/). ## Uninstalling Pro and your data[​](#uninstalling "Direct link to Uninstalling Pro and your data") Uninstalling the Pro plugin removes Pro's own operational data, but it **preserves your Pro settings (including the licence key) and your store configuration** so that reinstalling picks up where you left off. Shared translation data is only removed once the **free** plugin has also been uninstalled, so removing Pro alone never disturbs the free plugin. If you want a genuine clean slate — removing settings, licence, and store configuration as well — opt into a full wipe by defining `wcpos_remove_all_data` before uninstalling. Without it, uninstalling is safe and reversible. ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### Activation Failures[​](#activation-failures "Direct link to Activation Failures") * **"Invalid licence key"** — double-check for trailing spaces when pasting, and confirm the email address matches the one used at purchase. * **"Licence limit reached"** — by default a licence activates on **2 domains** (intended for one live site and one staging site). Note that **subdomains count as separate activations** — `example.com`, `staging.example.com`, and `dev.example.com` are three. This often catches hosts like Pantheon with mandatory dev/test/live environments. Deactivate unused sites from your [account page](https://wcpos.com/my-account/), or email **** — extra activations are routinely granted on request. ### Expired Licence[​](#expired-licence "Direct link to Expired Licence") * When a licence expires, Pro features remain active but you won't receive updates. * Renew from your [account page](https://wcpos.com/my-account/) — the existing key stays the same. ### Domain Transfers[​](#domain-transfers "Direct link to Domain Transfers") * If you've moved your site to a new domain, deactivate the licence on the old domain first, then reactivate on the new one. * If the old domain is no longer accessible, contact **** to reset the activation. ### Licence Server Connectivity[​](#licence-server-connectivity "Direct link to Licence Server Connectivity") * Activation requires your WordPress server to reach the WCPOS licence server. * If activation fails silently, check that outbound HTTPS requests aren't blocked by your host's firewall or a security plugin. * Some managed hosts block external API calls by default — contact your host to whitelist `wcpos.com`. ### Checking Licence Status[​](#checking-licence-status "Direct link to Checking Licence Status") * Go to `WP Admin > POS > Settings > License` to see your current activation status. * Your [account page](https://wcpos.com/my-account/) shows all active sites and expiry date. ## Purchase a License[​](#purchase-a-license "Direct link to Purchase a License") Visit [wcpos.com/pro](https://wcpos.com/pro) to purchase a Pro license. Buying and upgrading happen on the website There's no in-app "upgrade to Pro" button — purchases, plan upgrades, and renewals are all handled on [wcpos.com](https://wcpos.com/pro) and your [account page](https://wcpos.com/my-account/). After buying, install Pro using the [steps above](#installation). --- # Roadmap WCPOS is under active development. This page is the single place to check **what's coming**, follow progress, and tell us what you need. ## The public roadmap[​](#the-public-roadmap "Direct link to The public roadmap") The live, always-current source of truth is our public roadmap board on GitHub. It shows what's in progress, what's up next, and the wider backlog: [WCPOS Roadmap on GitHub →In progress, up next, and backlog — updated continuously as work moves.](https://github.com/orgs/wcpos/projects/4) Direction, not promises The roadmap reflects what we're working on and exploring — **not committed dates or guarantees**. Priorities shift based on what users need most. If a feature is critical to you, tell us (below) — demand is the biggest factor in what we build next. ## Request or vote on a feature[​](#request-or-vote "Direct link to Request or vote on a feature") The best way to influence what we build is to ask: * **[Discord](https://wcpos.com/discord)** — the fastest way to reach us and the community. Share your use case in `#general` or `#forum`. * **[GitHub Discussions](https://github.com/orgs/wcpos/discussions)** — propose a feature or add your "+1" and use case to an existing one. Many roadmap items started as a discussion. When you ask, tell us *what you're trying to do* and *why* — concrete use cases shape the design far more than a feature name. ## What we're working on[​](#what-were-working-on "Direct link to What we're working on") A high-level view of the themes in development. For the detailed, current status of any item, check the [roadmap board](https://github.com/orgs/wcpos/projects/4). ### At the register[​](#at-the-register "Direct link to At the register") * **Offline checkout** — complete a sale without a connection, starting with cash, and let it sync when you're back online * **Checkout conditions** — require things like a customer, an order note, or a custom field before an order can be completed * **Split & partial payments** — pay a single order with more than one method (e.g. part cash, part card) * **Cash management** — opening cash float, and formal shift start/stop for accurate end-of-day reporting ### Reporting & documents[​](#reporting-and-documents "Direct link to Reporting & documents") * **Reporting templates** — configurable Z-reports and shift summaries, printable to A4 or thermal * **Email templates** — POS-specific email/receipt layouts, separate from your standard order emails ### Selling more product types[​](#selling-more-product-types "Direct link to Selling more product types") Compatibility with more WooCommerce extensions — **Product Add-Ons**, **Product Bundles**, **Composite Products**, **Bookings**, **Product Options**, and **embedded (scale) barcodes**. ### Hardware & displays[​](#hardware-and-displays "Direct link to Hardware & displays") * **More card readers** and direct reader integrations * **Customer-facing display** — a second screen showing the order and total to the customer * **Order notifications** — real-time alerts for new online orders (great for restaurants) ## Already shipped[​](#already-shipped "Direct link to Already shipped") Recently landed highlights — see the docs for each: [New sync engine (v1.10)Rebuilt syncing: lighter on your server, honest download coverage, offline write recovery.](/reference/sync-engine.md) [Store health (v1.10)Sync presets, measured server load, coverage, and the activity log.](/support/store-health.md) [Prevent overselling (v1.10)Block out-of-stock items at the cart, with the server validating stock at checkout.](/settings/wp-admin/checkout.md#prevent-overselling) [Coupons at the tillSearch, apply, and stack coupons during a sale.](/coupons/.md) [RefundsProcess refunds to the original method or cash.](/orders/refunds.md) [Cloud printingPrint to printers that aren't attached to the till.](/receipts/cloud-printing.md) [Thermal receiptsDesign thermal receipt layouts for Epson and Star printers.](/receipts/thermal-templates.md) --- # Hardware WCPOS works with the physical devices you already use at the counter. This page is the starting point for connecting hardware — receipt printers, barcode scanners, card readers, and cash drawers. Each device type either has its own setup page here, or points to the page where its setup actually lives. ## Devices[​](#devices "Direct link to Devices") [Receipt PrintersConnect a thermal or network printer over USB, Bluetooth, or the network. Covers Epson, Star, and generic printers.](/hardware/printers/.md) [Barcode ScannersCamera, USB, and Bluetooth scanners — how they connect, the guided setup wizard, and step-by-step fixes when a scan doesn't come through.](/hardware/scanners/.md) [Card Readers & TerminalsCard readers are set up with their payment gateway — see Stripe Terminal, SumUp, and the other gateway guides under Payment Gateways.](/payment/gateways/.md) [Cash DrawersA cash drawer is kicked open by the receipt printer it's wired to — set it up on the Receipt Printers page.](/hardware/printers/cash-drawer.md) One home per device The Hardware hub points you to each device's setup, but the actual steps live in a single place. A card reader's account and pairing flow lives on its Payment Gateway page; a cash drawer's wiring and kick setting live on the Cash Drawer page. ## Card reader compatibility[​](#card-reader-compatibility "Direct link to Card reader compatibility") Which card readers work depends on **how you run WCPOS** and on the reader's connection type: * **The web app** can only drive readers that offer a **web (browser) SDK** — typically internet-connected countertop terminals. **Bluetooth-only** readers (e.g. Stripe M2 / WisePad 3, SumUp Air) and phone **Tap-to-Pay** are **not supported** in the web app. * Support is **per gateway**, not universal — check the reader against the gateway you plan to use ([Stripe Terminal](/payment/gateways/stripe-terminal.md), [SumUp](/payment/gateways/sumup-terminal.md), [PayPal Reader](/payment/gateways/paypal-reader.md)) before buying. Each gateway page lists the exact readers it supports. --- # Receipt Printers Printer settings live under **POS → Settings → Printing**. Each device keeps its own printers — they are stored on the till, not synced between devices. Printing to a printer that isn't at this till? This page covers printers attached to the till by USB or Bluetooth, or on the same Wi-Fi. For a printer in another room or another shop — or one every device should share — see [Cloud Printing](/receipts/cloud-printing.md). Cloud printers appear in every device's printer list automatically; you don't add them here. ## Add a printer[​](#adding-a-printer "Direct link to Add a printer") 1 #### Scan Go to **Settings → Printing** and tap **Add printer**. One scan looks for USB, Bluetooth and Wi-Fi printers at the same time — there is nothing to choose first. Each printer it finds appears as a card as soon as it turns up. 2 #### Print a test page Tap **Print a test page** on the card for your printer. The test page is a numbered ruler across the paper, so it shows the width is right as well as that the printer works. If the app doesn't already know how wide the paper is, it asks **58 mm** or **80 mm** first. 3 #### Answer the question The app then asks **Did the test page print?** There are three answers: * **Yes** — the printer is saved and you're done. * **Printed, but the ruler is off** — the app asks which paper is in the printer and prints the test page again on your answer. See [Getting the receipt width right](/hardware/printers/receipt-width.md). * **Nothing came out** — you get a one-line explanation of the most likely cause, and what to do about it. 4 #### Name it Once saved, the printer's **name**, **paper width** and **cash drawer** setting sit under its row in **Settings → Printing**. Change them there at any time. ### While the scan is running[​](#while-the-scan-is-running "Direct link to While the scan is running") Three buttons sit beside the results: * **Find a Bluetooth printer** — opens your browser's or computer's own Bluetooth chooser. Chrome and the desktop app put printer-like names at the top of the list. * **Enter an IP address** — stops the scan and checks one address instead. Use this when you know where the printer is and the scan can't see it, which is common on business networks. * **Stop** — halts the scan. Anything already found stays on screen. ## When nothing prints[​](#when-nothing-prints "Direct link to When nothing prints") Every trouble screen gives you one line saying what's wrong and what to do, plus two buttons: * **Copy setup report** — copies what the app tried, what the printer answered, and which connections were open. Paste it into a support message; it saves a long exchange of questions. * **Open the printer guide** — brings you here. Pick the guide that matches: **Setting up** * [Getting the receipt width right](/hardware/printers/receipt-width.md) — the ruler overshoots or falls short * [Give the printer a fixed address](/hardware/printers/network-address.md) — nothing found on Wi-Fi, or a printer that stopped working * [Pairing a Bluetooth receipt printer](/hardware/printers/bluetooth-pairing.md) — it isn't in the chooser * [USB on Windows](/hardware/printers/usb-windows.md) and [USB on Linux](/hardware/printers/usb-linux.md) * [Supported receipt printers](/hardware/printers/supported-printers.md) **Epson prints nothing** * [Epson Secure Printing](/hardware/printers/secure-printing.md) — a new Epson that appears to send and prints nothing * [Server Direct Print](/hardware/printers/server-direct-print.md) — its web page works but no job prints * [Printed once and then stopped](/hardware/printers/printed-once-then-stopped.md) — power-cycle first **Permissions** * [iPad and iPhone](/hardware/printers/ios-local-network.md) * [Android](/hardware/printers/android-permissions.md) * [Browser](/hardware/printers/browser-permissions.md) **Something on the receipt is wrong** * [The logo is missing in the browser](/hardware/printers/logo-missing-browser.md) * [Receipts in Chinese, Thai, Arabic or Cyrillic](/hardware/printers/non-latin-receipts.md) * [Connecting a cash drawer](/hardware/printers/cash-drawer.md) ## What each app can connect to[​](#supported-printers-by-platform "Direct link to What each app can connect to") | | Over Wi-Fi | Over USB and Bluetooth | | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Web app** | Epson and Star, through the printer's own web port. On an HTTPS store, Chrome asks for permission to reach your local network the first time. | USB and Bluetooth Low Energy through the browser's own device chooser — Chrome and Edge only. | | **Desktop app** | Any Wi-Fi receipt printer. It scans the network to find them. | USB, Bluetooth Low Energy, and printers already installed or paired in the operating system. | | **iPhone and iPad** | Any Wi-Fi receipt printer. | Epson and Star through the manufacturers' own software; other makes over Bluetooth Low Energy. | | **Android** | Any Wi-Fi receipt printer. | Epson and Star through the manufacturers' own software; other makes over Bluetooth Low Energy, or Bluetooth Classic once [paired in Settings](/hardware/printers/bluetooth-pairing.md#android-pair-first). | A browser can't open a direct connection to a printer the way an app can, which is why the web app reaches Epson and Star over Wi-Fi but not other makes — those two have a web server built in. For anything else on Wi-Fi, use the desktop or mobile app, or a [cloud printer](/receipts/cloud-printing.md). ## Printer options[​](#printer-options "Direct link to Printer options") Under each printer's row in **Settings → Printing**: | Option | What it does | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paper width** | How many characters fit on a line. Set by the test page — see [receipt width](/hardware/printers/receipt-width.md). | | **Auto-cut paper** | Cut the paper after each receipt. | | **Auto-open cash drawer** | Pop a drawer wired to this printer — see [cash drawers](/hardware/printers/cash-drawer.md). | | **Set as default** | Use this printer for any receipt that isn't routed elsewhere. | | **Full receipt raster** | Print the receipt as an image instead of text. Slower, but prints any language — see [non-Latin receipts](/hardware/printers/non-latin-receipts.md). | Looking for "auto-print after checkout"? Printing a receipt automatically when a sale completes is a **cart setting**, not a printer setting — turn on **Auto-print receipt** in the POS cart settings. *Which* printer it uses is decided by your default printer and by print routing. ## Print routing[​](#print-routing "Direct link to Print routing") If you use more than one template — say a thermal receipt **and** an A4 invoice — print routing decides which printer each template prints to. Routing has three layers, checked in this order: 1. **Per-job override.** On the receipt screen, a printer dropdown sits next to the template switcher. Picking a printer here overrides everything for that one print job. Switching templates resets it back to **Auto**. 2. **Settings override.** Go to **POS → Settings → Printing**, then use the **Receipt templates** section to assign a specific printer to each template. Set a template back to **Auto** to remove the override. 3. **Auto-match.** With no override, WCPOS matches automatically: thermal templates go to a thermal printer whose width matches (a 58 mm template prefers 32-column printers; an 80 mm template prefers 42 or 48), and HTML templates go to the system print dialog. If several printers match, the **default** printer wins. If you send a template to an incompatible printer — a thermal template to the system dialog, say — an amber **mismatch warning** appears on the receipt screen. The print still goes ahead, but it may not come out right. Routing is stored **per device**; each till manages its own. note The **Receipt templates** controls only appear once at least one printer is added. With no printers, every template uses the system print dialog. Cloud printers count here too — they appear as routing targets automatically. --- # Printer permissions on Android **Symptom:** on an Android phone or tablet the scan finds nothing, a Bluetooth printer never appears in the chooser, or a printer at a known address times out. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") Android gates these separately, and a denial is silent — a blocked connection times out exactly like a printer that's switched off. * **Nearby devices** covers finding and connecting to Bluetooth printers. * **Local network** access is required on recent Android versions before an app can reach anything on your Wi-Fi. ## Turn the permissions on[​](#turn-the-permissions-on "Direct link to Turn the permissions on") 1. Open Android **Settings → Apps → WCPOS → Permissions**. 2. Allow **Nearby devices**. 3. If **Local network** is listed, allow that too. Older Android versions don't have it. 4. Close the app and open it again, then scan. ## Bluetooth printers[​](#bluetooth-printers "Direct link to Bluetooth printers") On Android, Epson and Star printers connect through their manufacturer's own software, and they must be **paired in Android first** — **Settings → Connected devices → Pair new device** — before they show up in the app. Small Bluetooth Low Energy printers are picked in the app's own chooser instead; don't pair those in Android. See [Pairing a Bluetooth receipt printer](/hardware/printers/bluetooth-pairing.md). ## Wi-Fi printers[​](#wi-fi-printers "Direct link to Wi-Fi printers") Check the tablet is on the shop's Wi-Fi rather than mobile data or a guest network. If the scan comes back empty but you know the printer's address, use **Enter an IP address** — it checks the one address directly and doesn't depend on discovery. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message. [Discord Community](https://wcpos.com/discord) --- # Pairing a Bluetooth receipt printer **Symptom:** **Find a Bluetooth printer** opens the chooser and your printer isn't in the list — or it was there yesterday and isn't today. ## Turn the printer off and on[​](#turn-it-off-and-on "Direct link to Turn the printer off and on") This is the first thing to try and it fixes most cases. A printer that dropped a connection often stops advertising itself until it restarts. ## Only one device at a time[​](#one-device-at-a-time "Direct link to Only one device at a time") A Bluetooth printer talks to **one host at a time**. If it is still connected to a phone, a tablet or a laptop somewhere in the shop, it stops advertising and no other device can see it — including this one. Disconnect it there (or switch that device's Bluetooth off), then scan again. ## Classic or Low Energy[​](#classic-or-low-energy "Direct link to Classic or Low Energy") There are two kinds of Bluetooth printer, and they don't reach the same apps: * **Bluetooth Low Energy (BLE)** — most small 58 mm printers. These appear in the browser's and desktop app's choosers. Do **not** pair them in your computer's or phone's Bluetooth settings; pick them in the app's chooser instead. * **Bluetooth Classic** — most Epson and Star models, and many cheap 58 mm printers on Android. Pair these in the operating system first (**Settings → Bluetooth** / **Connected devices**), then add them in the app. On iPhone and iPad this works for Epson and Star printers only. ## On Android, pair it first[​](#android-pair-first "Direct link to On Android, pair it first") The Android app lists the Bluetooth Classic printers your phone has **already paired**; it cannot pair one itself. Open **Settings → Connected devices → Pair new device**, pick the printer (the PIN is usually `0000` or `1234`), then come back and scan again. The **Open Bluetooth settings** button on the "No printer found" screen takes you straight there. A printer that is paired but switched off still shows up as a card; turn it on before the test page. If the printer also speaks Bluetooth Low Energy, the app shows it once, as the Low Energy card, and no pairing is needed. ## Find its Bluetooth name[​](#find-its-name "Direct link to Find its Bluetooth name") Print the printer's status sheet — hold the **Feed** button (on an Epson, with the roll cover open) — and read the Bluetooth name and address off it. That tells you which entry in the chooser is yours when several look alike. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message. [Discord Community](https://wcpos.com/discord) --- # Printing from the browser: permissions and certificates **Symptom:** the POS runs in a browser and can't reach the printer — the scan finds nothing, or the same printer prints from the desktop app but not from the browser tab. ## Allow local network access[​](#allow-local-network-access "Direct link to Allow local network access") Chrome and Edge ask permission before a website may talk to a device on your network. If that prompt was dismissed, every attempt fails silently. Click the icon at the left of the address bar → **Site settings** → set **Local network** to **Allow**, then reload the page and scan again. ## Mixed content[​](#mixed-content "Direct link to Mixed content") A POS served over `https://` cannot open a plain `http://` connection to a printer. Chrome and Edge allow it once you've granted local network access; other browsers block it outright. If your store runs on HTTPS and the printer only speaks HTTP, use the desktop app. ## The printer's certificate[​](#the-printers-certificate "Direct link to The printer's certificate") Printers secure themselves with their own certificate, which no browser trusts by default — the connection fails before it starts. Open `https://printer-ip` in the same browser once, accept the warning, and go back to the POS. You'll need to do this on each computer. The desktop app doesn't have this problem: it accepts the printer's certificate itself, which is why the same printer works there and not in the tab. ## Safari and Firefox[​](#safari-and-firefox "Direct link to Safari and Firefox") Neither has any of these routes. They have no local network permission to grant, and no support for USB or Bluetooth printers from a web page. On those browsers use a Wi-Fi printer that matches your store's HTTP or HTTPS, or use the desktop app. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message — it records which browser and which lane were tried. [Discord Community](https://wcpos.com/discord) --- # Connecting a cash drawer to the printer A cash drawer isn't connected to the POS at all. It plugs into the **receipt printer**, and the printer pops it open when a receipt prints. ## Wire it up[​](#wire-it-up "Direct link to Wire it up") 1. Plug the drawer's cable — it looks like a telephone plug — into the socket on the printer marked **DK**, **Drawer** or **Cash Drawer**. 2. Don't use the network socket beside it. It's the same shape and slightly wider; the drawer cable is the narrower one. 3. Switch the printer off and on. ## Switch it on in the app[​](#switch-it-on-in-the-app "Direct link to Switch it on in the app") Open **Settings → Printing**, find the printer's row, and turn on **Auto-open cash drawer**. The drawer then opens each time that printer prints a receipt. ## When it doesn't open[​](#when-it-doesnt-open "Direct link to When it doesn't open") * **Check the drawer's key.** Many drawers have a lock on the front with a position that disables the release entirely. * **Try the printer's own test.** Most printers pop the drawer during their self-test. If that doesn't open it either, the problem is the cable or the drawer, not the POS. * **Low-cost printers may not respond.** Some clones only understand an older version of the open command, and some don't drive the drawer at all. The printer's manual will say whether it supports a cash drawer. * **Check the voltage.** Drawers come in 12 V and 24 V versions. A 24 V drawer on a 12 V printer socket clicks but doesn't have the force to open. * **The browser's print dialog can't open a drawer.** The receipt has to be routed to the thermal printer itself. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** and paste it into your message, with the printer and drawer models. [Discord Community](https://wcpos.com/discord) --- # Let the app find printers on your iPad or iPhone **Symptom:** on an iPad or iPhone the scan finds nothing, or a printer at an address you know is correct simply times out. The same printer works from a computer on the same Wi-Fi. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") iOS asks once, on first use, whether an app may talk to devices on your local network. If that prompt was declined — or was answered by someone else, or never appeared — every scan and every print is blocked from then on. iOS gives the app no error saying so, which is why it looks identical to a printer that's off. ## Turn the permission on[​](#turn-the-permission-on "Direct link to Turn the permission on") 1. Open the iPad or iPhone's **Settings** app. 2. Go to **Privacy & Security → Local Network**. 3. Turn on the switch for **WCPOS**. 4. Close the app completely (swipe it away from the app switcher) and open it again. Then go to **Settings → Printing → Add printer** and scan again. ## Also check[​](#also-check "Direct link to Also check") * The iPad is on the **shop's Wi-Fi**, not a guest network and not mobile data. See [Give the printer a fixed address](/hardware/printers/network-address.md). * Wi-Fi is on. With Wi-Fi off, a printer at a local address is unreachable however the permission is set. ## If the scan finds nothing but the printer works[​](#if-the-scan-finds-nothing "Direct link to If the scan finds nothing but the printer works") Scanning relies on the printer announcing itself, which some networks block. Use **Enter an IP address** instead — it stops the scan and checks the one address directly. Print the printer's status sheet to read the address off it. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message — it records what the iPad tried and what came back. [Discord Community](https://wcpos.com/discord) --- # The logo is missing from receipts printed in the browser **Symptom:** receipts printed from a browser tab come out complete except for the store logo. The same receipt from the desktop or mobile app prints the logo normally. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") The logo lives in your WordPress media library, and the browser fetches it from there. Before a web page may read the pixels of an image loaded from another address, the server holding it has to say so with a header called `Access-Control-Allow-Origin`. WordPress doesn't send that header on uploaded files by default, so the browser hands over the picture to display but not to print. The app can't work around it — it prints the receipt without the logo rather than failing the sale. The desktop and mobile apps fetch the file themselves and aren't subject to the rule. ## Do this[​](#do-this "Direct link to Do this") Pick whichever suits the shop: * **Print from the desktop app.** Nothing to configure, and it is the quickest answer if the till already has it installed. * **Allow the header on your site.** Whoever manages the site adds `Access-Control-Allow-Origin` for the uploads directory, in the web server configuration or with a plugin that sets CORS headers. Reload the POS afterwards and print again. ## If the logo prints as noise[​](#if-the-logo-prints-as-noise "Direct link to If the logo prints as noise") A band of random dots instead of the logo is a different problem: some older and low-cost printers can't decode the image format used. Remove the logo from that printer's receipt template. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message, along with the address of the logo image. [Discord Community](https://wcpos.com/discord) --- # Give the printer a fixed address on the same network **Symptom:** the scan finds nothing over Wi-Fi, or a printer that worked for weeks suddenly times out on every receipt. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") Three network conditions cause almost all of it: * **Different networks.** The till is on one Wi-Fi and the printer on another — a guest SSID, a second access point, or a separate VLAN. Printer discovery does not cross between them. * **Client isolation.** Guest and public Wi-Fi usually blocks devices from talking to each other at all. The printer is on the same network and still unreachable. * **The address changed.** Your router hands out addresses on a lease. When the lease changes, the printer moves to a new address while the saved printer still points at the old one — so it worked yesterday and times out today. ## Do this[​](#do-this "Direct link to Do this") 1. Put the till and the printer on the **same Wi-Fi**, not the guest network. 2. Print the printer's status sheet to read its current address. On an Epson, open the roll cover and hold **Feed** for a second; on a Star, hold **Feed** for five seconds while it's switched on. 3. Give it a **fixed address**: reserve one for the printer's MAC address in your router's DHCP settings, or set a static address in the printer's own web page at `http://printer-ip`. Either way it stops moving. 4. In the app, use **Enter an IP address** and type it in. That stops the scan and checks the one address directly, which works even when discovery is blocked. If the address is right and it still times out, the printer may be holding a job — see [printed once and then stopped](/hardware/printers/printed-once-then-stopped.md). ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message — it lists the address tried and which ports answered. [Discord Community](https://wcpos.com/discord) --- # Receipts in Chinese, Thai, Arabic or Cyrillic **Symptom:** the receipt on screen is correct, but the paper shows question marks, empty boxes, or the wrong letters entirely. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") A thermal printer doesn't use the fonts on your computer. It prints from character tables built into its own firmware — one table active at a time, and most printers leave the factory on a Latin one. Anything the active table has no character for is replaced before it reaches the paper, which is where the question marks come from. ## Print the receipt as an image[​](#print-the-receipt-as-an-image "Direct link to Print the receipt as an image") This is the reliable fix and it works for every language. Open **Settings → Printing**, find the printer's row, and turn on **Full receipt raster**. The receipt is then drawn as a picture and sent to the printer as one, so it prints exactly as it appears on screen — Chinese, Thai, Arabic, Hebrew, Cyrillic, Greek, accented Latin, all of it. It is slower than printing text, because an image is much larger to send. Turn it on for the printers that need it, not for all of them. ## Or set the receipt language in the app[​](#or-set-the-receipt-language-in-the-app "Direct link to Or set the receipt language in the app") Under the printer's **More options** (when adding it) or **Advanced** (when editing it) there is a **Receipt language** setting. It tells the app which character table to write text with: Western or Central European, Cyrillic, Greek, Turkish, Arabic, Hebrew, Thai or Vietnamese. The printer must hold the same table, which most do. Chinese, Japanese and Korean have no entry yet, so for those scripts use the image method above. ## Or change the printer's character table[​](#or-change-the-printers-character-table "Direct link to Or change the printer's character table") If you'd rather keep the speed of text printing, set the printer's default character table to one that covers your language, using the manufacturer's setup tool or the printer's web page. Its manual lists the tables it holds. Note that one table rarely covers two scripts, so a receipt mixing languages still needs the image method. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** and paste it into your message, with a photo of the printed receipt and the language you're printing. [Discord Community](https://wcpos.com/discord) --- # Epson printed once and then stopped — power-cycle first **Symptom:** one receipt printed, then nothing. The app says *"Turn the printer off and on again, then try again."* The printer looks healthy — ready light on, paper in, self-test prints from the panel. ## Power-cycle it first[​](#power-cycle-first "Direct link to Power-cycle it first") Unplug the printer, count to ten, plug it back in and wait for the ready light. Then print a test page. Do this before changing any setting. It is the fastest way to tell a stuck printer from a misconfigured one, and it fixes the case below outright. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") An Epson can accept a job it has no intention of printing — most often one that arrived on a channel the printer is set to block. It doesn't reject it; it **holds** it. And while it holds one job, it won't print anything from any channel: not the next receipt, not the app's test page. The hold clears itself after a few minutes, or immediately when the printer restarts. That's why a printer can look fine and behave as though it's dead, and why the same printer starts working again while you're still investigating. ## If it comes back[​](#if-it-comes-back "Direct link to If it comes back") A power cycle treats the symptom. If it keeps happening, something is still sending jobs down a blocked channel: * Check [Secure Printing](/hardware/printers/secure-printing.md) — the usual cause on printers bought since mid-2025. * Check [Server Direct Print](/hardware/printers/server-direct-print.md) if the printer's web page works but nothing prints. Scanning for printers can trigger the hold too, so a printer that jams shortly after you tap **Add printer** is showing the same problem. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message. [Discord Community](https://wcpos.com/discord) --- # Getting the receipt width right (58 mm, 80 mm, 42 or 48 characters) The test page prints a numbered ruler across the paper. If it doesn't end neatly at the edge, the app is printing the wrong number of characters per line, and every receipt after it will be crooked too. ## What "the ruler is off" means[​](#what-the-ruler-is-off-means "Direct link to What \"the ruler is off\" means") * The numbers **run past the edge** or wrap onto a second line — the app is printing more characters than fit. * The row **stops well short** of the edge — the app is printing fewer characters than fit, so columns of prices drift left. Answer **Printed, but the ruler is off** and the app asks which paper is in the printer, then prints the test page again on your answer. Keep going until the ruler ends at the edge. ## Which answer to pick[​](#which-answer-to-pick "Direct link to Which answer to pick") | Answer | Paper | Use it when | | --------------------------------- | ----- | ------------------------------------------- | | **32 — 58 mm paper** | 58 mm | Small, portable and most Bluetooth printers | | **48 — 80 mm, most Epson & Star** | 80 mm | Try this first on a full-size printer | | **42 — 80 mm, older printers** | 80 mm | 48 overshot the edge | | **64 — 80 mm, small font** | 80 mm | The printer is set to its small font | Measure the roll if you're unsure: 58 mm is about the width of two fingers, 80 mm about three. ## Font A and Font B[​](#font-a-and-font-b "Direct link to Font A and Font B") Receipt printers have two built-in fonts. Font A is the standard one; Font B is smaller and fits more characters on the same paper — which is why 64 exists on 80 mm. If 48 overshoots and 42 falls short, the printer has been left in the small font. Either pick 64, or set the printer back to Font A in its own setup tool. If the app doesn't already know the width, it asks **58 mm** or **80 mm** before it prints the first test page. You can change it later under the printer's row in **Settings → Printing**. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on any trouble screen and paste it into your message — it records the width the app is using and how the printer answered. [Discord Community](https://wcpos.com/discord) --- # Epson Secure Printing: what it blocks and how to turn it off **Symptom:** the app says *"Secure Printing is on. Turn it off on the printer, then try again."* Or a brand-new Epson is found on the network, the test page appears to send, and nothing comes out — no error, no light, and the printer's own status page says it's available. Panel self-tests print fine. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") Epson TM-series printers built for the EU and UK since **1 August 2025** ship with **Secure Printing** enabled, to meet the EU's Radio Equipment Directive. While it's on, the printer accepts jobs sent over the old unencrypted channels and then **silently discards** them. | Channel | Secure Printing **on** | **off** | | --------------------------------- | ------------------------ | ------- | | Raw TCP, port 9100 | Accepted, then discarded | Prints | | ePOS-Print over HTTP (80, 8008) | Not served | Prints | | ePOS-Print over HTTPS (443, 8043) | Prints | Prints | Units sold outside the EU can carry the same firmware. If a new Epson anywhere shows this symptom, check the setting. ## Turn it off[​](#turn-it-off "Direct link to Turn it off") You need the printer's admin password. On recent models that's the **serial number** on the label underneath the printer; older models used `epson`. 1. Find the printer's address — it's on the status sheet (open the roll cover, hold **Feed**). 2. Open `https://printer-ip` in a browser and accept the certificate warning. 3. **Administrator Login**, then **Print → Secure Printing**. 4. Set it to **Disable** and confirm. 5. Unplug the printer for ten seconds and plug it back in. 6. Print the test page again. A firmware update turns it back on Epson resets the security configuration to its defaults on firmware update. If a printer that worked for months stops right after an update, repeat these steps. While you're in there, set your own admin password — anyone on the same network can reach an open receipt printer. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** and paste it into your message. See also [Epson's Radio Equipment Directive FAQ](https://www.epson.co.uk/en_GB/faq/KA-01896/contents?loc=en-us). [Discord Community](https://wcpos.com/discord) --- # Epson prints nothing and its web page still works (Server Direct Print) **Symptom:** the printer's own web page loads, its panel self-test prints, Secure Printing is already off — and every job from the POS still fails or times out. A power cycle changes nothing. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") Epson printers can be told to fetch their own jobs from a server, a feature called **Server Direct Print**. A related feature, **ePOS-Device**, lets one application hold the printer open for a session. Either one takes ownership of the print engine, and while it's held the printer refuses everything else as busy — without saying so. Because it's a saved setting on the printer, restarting doesn't clear it. This is usually left on by a previous installation, a kitchen-printing service, or another till. ## Turn it off[​](#turn-it-off "Direct link to Turn it off") 1. Open `https://printer-ip` in a browser and accept the certificate warning. 2. **Administrator Login** — the password is the serial number on the label underneath the printer, unless someone changed it. 3. Find **Server Direct Print** (under the printer's services or print settings, depending on firmware) and set it to **Disable**. 4. On the same screen, check **ePOS-Device** is disabled too if nothing else is using it. 5. Confirm, then unplug the printer for ten seconds and plug it back in. 6. Print the test page again. Something else may be using it If another system genuinely prints through Server Direct Print — a kitchen display, an online-order service — only one of the two can own the printer. Point that system somewhere else, or give the POS its own printer. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message — it records how the printer answered on each port. [Discord Community](https://wcpos.com/discord) --- # Printer Setup Wizard Not sure how to connect your printer? Answer a few questions and we'll guide you. For full reference, see [Printer Setup](/hardware/printers/.md). ### Where is the printer? Right here — plugged into or on the same wifi/network as this tillSomewhere else — on another wifi/network, or connected to another computer BackStart over --- # Supported receipt printers Most receipt printers speak one of two command languages, ESC/POS or StarPRNT, so most of them print. These tiers say how confident we are about a given model. ## Verified[​](#verified "Direct link to Verified") Tested on real hardware here, on every connection listed. | Printer | Paper | Connections | | ------------------- | ----- | ---------------------------------------------------- | | **Epson TM-m30III** | 80 mm | Wi-Fi, USB, Bluetooth — web, desktop and mobile apps | | **Netum NT-1809** | 58 mm | USB and Bluetooth | New Epson printers need one setting changed before they print at all — see [Epson Secure Printing](/hardware/printers/secure-printing.md). ## Expected to work[​](#expected-to-work "Direct link to Expected to work") Not tested by us model by model, but built on the same interfaces as the verified printers. If yours is in this group and doesn't print, it's usually a network or permission problem rather than the printer. * **Epson TM-series** printers with ePOS, over Wi-Fi, USB or Bluetooth. * **Star mC-Print and TSP** printers with WebPRNT or StarPRNT. * **ESC/POS printers from other makers** over USB, or over Wi-Fi from the desktop app. * **Bluetooth Low Energy printers** — the small 58 mm class — in Chrome, Edge and the desktop app. ## Not supported yet[​](#not-supported-yet "Direct link to Not supported yet") * **Bluetooth Classic printers on iPhone and iPad.** iOS only lets Epson and Star printers talk to apps over Bluetooth Classic. For other makes, use Bluetooth Low Energy, USB or Wi-Fi, or an Android or desktop till. (On Android, Classic printers work once they are [paired in Settings](/hardware/printers/bluetooth-pairing.md#android-pair-first).) * **The built-in printer in Sunmi and iMin all-in-one terminals.** These use each maker's own interface rather than USB, Bluetooth or the network, so the app can't see them. An external printer works normally on those devices. ## Report yours[​](#report-yours "Direct link to Report yours") Whether it worked or not, tell us the model. Run **Settings → Printing → Add printer**, and on any trouble screen tap **Copy setup report** — it records the printer, how it answered, and which connections were open. Paste it into your message. [Discord Community](https://wcpos.com/discord) --- # USB printer permissions on Linux **Symptom:** the printer shows up when you scan, but printing fails with an access or permission error. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") On Linux a USB device belongs to `root` unless a rule says otherwise, so an app running as you cannot open it. The kernel's own printer driver may also have claimed the device already. ## Do this[​](#do-this "Direct link to Do this") 1. Find the printer's vendor and product ids: ``` lsusb ``` Look for your printer's line — the ids are the two four-character values after `ID`, for example `04b8:0e28`. 2. Create a rule file, replacing the ids with yours: ``` sudo tee /etc/udev/rules.d/99-receipt-printer.rules <<'RULE' SUBSYSTEM=="usb", ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0e28", MODE="0666" RULE ``` 3. Reload the rules and re-apply them: ``` sudo udevadm control --reload-rules && sudo udevadm trigger ``` 4. Unplug the printer, plug it back in, and restart the app. Print a test page. Run the app as your normal user, not with `sudo` — a rule that works only for root defeats the point. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message, along with the `lsusb` line for your printer. [Discord Community](https://wcpos.com/discord) --- # USB receipt printers on Windows: install a Generic/Text driver **Symptom:** the printer is listed, but the test page never arrives — or a page of stray letters, brackets and symbols comes out instead of a receipt. ## Why it happens[​](#why-it-happens "Direct link to Why it happens") On Windows, whichever driver you installed with the printer takes ownership of the USB port. The app can't reach the printer directly past it, so it prints through the printer's **installed Windows queue**. That works — as long as the queue passes the receipt commands through untouched. A queue bound to the manufacturer's own driver often re-renders or discards them, which is where the page of symbols comes from. ## Do this[​](#do-this "Direct link to Do this") 1. Open **Settings → Bluetooth & devices → Printers & scanners**. 2. Choose **Add device**, then **Add manually** when Windows fails to find it. 3. Select **Add a local printer**, and pick the printer's **USB** port from the list. 4. For the driver, choose the manufacturer **Generic** and the model **Generic / Text Only**. 5. Give the queue a name you'll recognise, and finish. 6. Back in the POS, open **Settings → Printing → Add printer**, scan again, and pick that queue. Print a test page. If a page of symbols still comes out, the app is still finding the vendor-driver queue. Delete it, or make sure you pick the Generic/Text one by name. ## Still stuck?[​](#still-stuck "Direct link to Still stuck?") Use **Copy setup report** on the trouble screen and paste it into your message — it names the queue the app used. [Discord Community](https://wcpos.com/discord) --- # Barcode Scanners WCPOS scans barcodes on every platform — with the device **camera**, with an ordinary **keyboard-mode** scanner, or over a **direct connection** to a USB or Bluetooth scanner. Most scanners work the moment you plug them in or pair them; the pages below cover guided setup, how scanning behaves at the till, and how to fine-tune detection. ## Ways to scan[​](#ways-to-scan "Direct link to Ways to scan") * **Camera** — available on web, desktop, iOS, and Android. Open the camera from the scan icon in the search bar; it appears as a resizable panel below the filters so the product list stays in view. No extra hardware required. * **Keyboard mode (HID)** — the factory default on almost every scanner. The scanner "types" the barcode and WCPOS recognises the fast keystrokes. Nothing to configure — plug in or pair and scan. * **Direct connection** — for scanners switched into a serial or POS mode: USB serial and HID-POS (via the browser's Web Serial and WebHID support), Bluetooth SPP, and Bluetooth LE over a vendor GATT service. Direct connections deliver every scan straight to WCPOS regardless of typing speed, keyboard layout, or which field is focused. Supported in the Desktop app and Chrome-based browsers; the Desktop app shows a device chooser inside the app. ## Get started[​](#get-started "Direct link to Get started") [Scanner Setup WizardAnswer a few questions and we'll walk you through connecting your scanner — and help you fix it if a scan doesn't come through.](/hardware/scanners/setup-wizard.md) [How scanning worksWhat happens when a barcode is detected, camera scanning, scan sounds, and the online fallback for unknown barcodes.](/pos/product-panel/barcode-scanning.md) [Barcode settingsTune detection so fast typing doesn't register, strip a scanner's prefix/suffix, test a scan, and turn on scan sounds.](/settings/store/barcode.md) [Barcode fieldChoose which product field holds the barcode — the GTIN field by default, or SKU or a custom meta key.](/settings/wp-admin/general.md#barcode-field) Which field is the barcode? WCPOS matches scans against a single configured barcode field, which defaults to WooCommerce's GTIN field (`_global_unique_id`). You can point it at `_sku` or any custom meta key in [Settings](/settings/wp-admin/general.md#barcode-field); changing it rebuilds the local barcode index automatically. --- # Scanner Setup Wizard ### What are you setting up? I have a barcode scanner and want to set it upMy scanner already types scans, but something's wrongI don't have a scanner — can I scan with a camera? BackStart over --- # Integrations WCPOS runs on the WooCommerce REST API, so most WooCommerce plugins work with POS orders without any extra setup. A few need WCPOS to do something on their behalf, because they only hook into the online checkout or the WP Admin order screen. The pages in this section cover those plugins: what WCPOS does for them, how to set them up, and what to expect at the till. This is different from [Extensions](/extensions/.md), which are add-ons built for WCPOS that you install from the extension directory. An integration is a plugin you already run for your online store. ## Tax[​](#tax "Direct link to Tax") [WooCommerce TaxAutomated sales tax through TaxJar. WCPOS asks WooCommerce Tax for rates when an open POS order saves.](/integrations/woocommerce-tax.md) ## Something not working?[​](#something-not-working "Direct link to Something not working?") If a plugin you rely on misbehaves with the POS, start with [Plugin Conflicts](/support/troubleshooting/plugin-conflicts.md): it lists known conflicts and how to identify a new one. --- # WooCommerce Tax [WooCommerce Tax](https://woocommerce.com/document/woocommerce-tax/) is the WooCommerce plugin that looks up sales tax automatically through TaxJar instead of you maintaining a rate table by hand. WCPOS works with it: POS sales get the same jurisdiction rates as your online orders, and nothing needs to be switched on in WCPOS. ## How it works[​](#how-it-works "Direct link to How it works") WooCommerce Tax only asks TaxJar for rates when an order goes through the online checkout or is edited on the WooCommerce order screen. POS orders take neither path, so WCPOS asks on their behalf: 1. When the POS saves an open order, WCPOS asks WooCommerce Tax for the rates at the order's tax location. The location follows the POS **Calculate Tax Based On** setting: the shop base address, or the customer's billing or shipping address. 2. WooCommerce Tax writes those rates into your store's normal tax rate table as one row per jurisdiction, exactly as it does for an online order. You will see them under `WP Admin > WooCommerce > Settings > Tax > Standard rates`, keyed by postcode and city. 3. WooCommerce applies the rows to the order. The order carries one tax line per jurisdiction, with WooCommerce Tax's own names (for example *CA STATE TAX*, *CA COUNTY TAX*). 4. The POS downloads the new rows on its next change check, usually within a minute, so its local totals agree with your store from then on. To fetch them straight away, use **Clear & re-download** on the **Tax rates** row under [Store health → Database](/support/store-health.md#clear-and-redownload). Adding or removing lines on an open POS order recalculates its tax from the current lines. Once an order is paid, WCPOS leaves it alone and WooCommerce Tax behaves as it does for any other order. With automated taxes off, WCPOS does nothing special and the POS uses your store's tax rate table as usual. ## Setup[​](#setup "Direct link to Setup") 1 #### Connect WooCommerce Tax Install and activate WooCommerce Tax and connect it to WordPress.com. `WP Admin > WooCommerce > Status > WooCommerce Tax` should say **Connected to WordPress.com**. 2 #### Enable automated taxes Under `WP Admin > WooCommerce > Settings > Tax`, set **Automated taxes** to **Enable automated taxes**. Your store must be in a country WooCommerce Tax supports. Turning this on backs up any rates you entered by hand to a CSV file and removes them from the table. Download the backup from `WP Admin > WooCommerce > Status > WooCommerce Tax` if you might need them again. 3 #### Mirror the settings in the POS In the POS, open [Tax Settings](/settings/store/tax.md) and click **Restore Server Settings**. While automated taxes are on, WooCommerce Tax locks WooCommerce to calculating tax from the customer's shipping address, with prices entered and displayed *excluding* tax, and the POS has to mirror those. If you deliberately keep the POS on the shop base address for walk-in sales, WCPOS uses that basis for POS orders on your store as well, so the two still agree. 4 #### Make a test sale Ring up a taxable product in the **Standard** tax class and let the order save. Check it in WP Admin: it should carry jurisdiction-named tax lines, and the matching rows should have appeared under **Standard rates**. Products in another tax class get rows under that class the first time a sale includes one. ## What to expect[​](#what-to-expect "Direct link to What to expect") * **The first sale at a new location can disagree once.** The POS totals a sale from the rate rows it has already downloaded. If your store has never taxed an address before, there is no row for it yet, so the POS may show the [totals notice](/support/troubleshooting/totals-disagree.md) on that one sale. Your store's figures are what is recorded. Once the row reaches the POS, usually within a minute, later sales at that location agree. With tax based on a customer address it can happen once per new postcode; with the shop base address, normally only on the very first sale. A jurisdiction changing its rate can cause it once more. * **Do not add rate rows by hand.** A location's rows appear on the first sale there. If **View all tax rates** in the POS looks empty for a location, that location has not been sold to yet. * **Fees are not sent to TaxJar.** A taxable fee is taxed with whatever rate your table already holds for the fee's tax class, which is how WooCommerce Tax treats fees on its own order screen too. * **A failed lookup never blocks a sale.** If TaxJar cannot be reached, or WooCommerce Tax declines to look the order up (no postcode on the address, a tax-exempt customer, a location where your store has no nexus), the order still saves with the rates already in your table. The POS logs on your server record which it was: *WooCommerce Tax rate priming failed* for an outage, *WooCommerce Tax returned no rates for the POS order* for a decline. See [Logs](/support/logs.md). * **Stripe Tax is different.** Stripe Tax does not work with POS orders at all. See [Plugin Conflicts](/support/troubleshooting/plugin-conflicts.md). ## Requirements[​](#requirements "Direct link to Requirements") WooCommerce Tax : Installed, connected to WordPress.com, with automated taxes enabled Store country : A country WooCommerce Tax supports for automated taxes WooCommerce : 7.6 or newer. On older WooCommerce, WCPOS does not ask WooCommerce Tax for rates and POS orders use whatever rows the table already holds WCPOS : Free and Pro ## Related[​](#related "Direct link to Related") * [Tax Settings](/settings/store/tax.md) * [Your Store and the POS Disagree on Totals](/support/troubleshooting/totals-disagree.md) * [Plugin Conflicts](/support/troubleshooting/plugin-conflicts.md) --- # Orders Pro Feature The Orders screen requires [WCPOS Pro](/getting-started/pro-license.md). The Orders screen provides access to your order history directly within the POS. View past orders, reprint receipts, and manage order details without switching to the WooCommerce admin. ## Interface Overview[​](#interface-overview "Direct link to Interface Overview") ### Search & Filters[​](#search--filters "Direct link to Search & Filters") At the top of the screen: * **Search bar** - Find orders by number, customer name, etc. * **Status filter** - Filter by order status (Completed, Processing, etc.) * **Customer filter** - Filter by customer * **Cashier filter** - Filter by who processed the order * **Store filter** - Filter by store (for multi-store setups) * **Date Range** - Filter by date Active filters appear as blue badges that can be removed by clicking the ×. ### Orders Table[​](#orders-table "Direct link to Orders Table") The main area displays orders with: * **Status icon** - Visual indicator (✓ completed, 🕐 pending, 🛒 open) * **Order Number** - Unique order ID * **Customer** - Customer name (or "Guest") * **Billing Address** - Customer billing information * **Note indicator** - Speech bubble when order has notes * **Date Created** - Relative timestamps ("2 hours ago") * **Cashier** - Who processed the order * **Payment Method** - Cash, Card, etc. * **Total** - Order total amount * **Actions** - Three-dot menu Filtering and paging cover your whole store Filtering — by status, customer, cashier, store, or date range — runs on the **server**, so it spans all your orders, not just those already on the device, and the list keeps loading more as you scroll. Sort by clicking a column header. ### Footer[​](#footer "Direct link to Footer") * Order count with sync button (). **Long press** for Clear and Refresh option ## Key Features[​](#key-features "Direct link to Key Features") ### Order Lookup[​](#order-lookup "Direct link to Order Lookup") Quickly find orders using: * **Order number search** * **Customer name search** * **Date range filtering** * **Status filtering** * **Cashier filtering** ### Receipt Reprinting[​](#receipt-reprinting "Direct link to Receipt Reprinting") For any order, you can: 1. Click the three-dot menu 2. Select the receipt option 3. View, print, or email the receipt ### Order Details[​](#order-details "Direct link to Order Details") Click an order to view: * Complete line item details * Customer information * Payment details * Order notes * Meta data ## Display Settings[​](#display-settings "Direct link to Display Settings") Click the sliders icon () to customise visible columns. ![Orders Settings](/img/orders-page-settings.png) Orders Display Settings ### Available Columns[​](#available-columns "Direct link to Available Columns") #### Essential columns[​](#essential-columns "Direct link to Essential columns") The core columns most stores keep visible — they identify the order and let you act on it. | Column | Description | | ---------------- | ------------------------- | | **Status** | Order status icon | | **Order Number** | Unique order ID | | **Customer** | Customer name and details | | **Total** | Order total | | **Receipt** | Quick receipt access | | **Actions** | Edit, view, etc. | #### Optional columns[​](#optional-columns "Direct link to Optional columns") Extra detail you can switch on when you need it — addresses, dates, and order metadata. | Column | Description | | -------------------- | -------------------------------- | | **Billing Address** | Billing information | | **Shipping Address** | Shipping information | | **Customer Note** | Notes from customer | | **Date Created** | When order was placed | | **Date Modified** | Last modification | | **Date Completed** | When order completed | | **Date Paid** | When payment received | | **Created Via** | Order source (POS, Online, etc.) | | **Cashier** | Who processed the order | | **Payment Method** | Payment type used | ## Order Actions[​](#order-actions "Direct link to Order Actions") Click the three-dot menu (⋮) for options: * **View** - See full order details * **Edit** - Modify order information * **Receipt** - View/print/email receipt * **Sync** - Refresh order from server ### Editing Orders[​](#editing-orders "Direct link to Editing Orders") Select **Edit** from the three-dot menu to modify an existing order. This reopens the order in the cart, where you can: * Add or remove line items * Change quantities or prices * Update the customer * Add notes or metadata After making changes, proceed through checkout again to save the updated order. ### Order Statuses[​](#order-statuses "Direct link to Order Statuses") POS orders use standard WooCommerce order statuses plus one custom status: Typical order flow An order generally progresses **POS - Open → Pending → Processing → Completed**, with **Cancelled** or **Refunded** as end states. Most POS orders skip straight to **Completed** because payment is collected at the point of sale. | Status | Description | | -------------- | ------------------------------------------------------------------- | | **POS - Open** | Order saved from the POS but not yet completed (parked/held orders) | | **Pending** | Awaiting payment | | **Processing** | Payment received, order is being fulfilled | | **Completed** | Order fulfilled and complete | | **Cancelled** | Order was cancelled | | **Refunded** | Order was fully refunded | Most POS orders go directly to **Completed** since payment is collected at the point of sale. Open orders (saved with the **Save to Server** button in the cart) use the **POS - Open** status and can be reopened later to continue the transaction. ### Refunds[​](#refunds "Direct link to Refunds") You can issue full or partial refunds directly from the POS — either back to the original payment method (when the gateway supports it) or as cash from the till. Open the three‑dot menu (⋮) on an order and choose **Refund**, or click the **Refund** button in the order view footer. See [Refunds](/orders/refunds.md) for the full walkthrough, including refund destinations, partial refunds, and how refunds appear on receipts. ## Use Cases[​](#use-cases "Direct link to Use Cases") #### Customer Service * Look up past orders to assist with returns or inquiries * Verify what a customer purchased * Reprint receipts on request #### End of Day * Review all orders for the day * Filter by cashier to verify individual totals * Cross-reference with [Reports](/reports/.md) for reconciliation #### Order Tracking * Monitor order statuses * Track which orders are pending vs completed * Identify orders that need attention ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [ReportsSales reports and reconciliation](/reports/.md) [ReceiptsReceipt customisation](/receipts/at-checkout.md) --- # Refunds Pro Feature Issuing refunds from the POS requires [WCPOS Pro](/getting-started/pro-license.md). Without Pro, you can still process refunds from `WP Admin → WooCommerce → Orders` using WooCommerce's built‑in refund interface. WCPOS lets you refund a WooCommerce order without leaving the register. You can issue a full or partial refund, send the funds back to the original payment method (when the gateway supports it), or record a cash refund from the till — and the refund is tagged with the cashier and store that processed it for reporting. ## Starting a Refund[​](#starting-a-refund "Direct link to Starting a Refund") There are two ways to open the refund form: 1. **From the Orders list** — find the order, click the three‑dot menu () in the actions column, and select **Refund**. 2. **From the order view modal** — open the order, then click the **Refund** button in the footer next to **Print Receipt** and **Cancel**. Both routes open the same **Refund Order #{number}** modal. ### When the Refund Action Appears[​](#when-the-refund-action-appears "Direct link to When the Refund Action Appears") **Refund** is only offered for orders with the following statuses: * **Completed** * **Processing** * **On hold** It does **not** appear on `Pending`, `Cancelled`, `Failed`, `POS – Open`, or already fully‑`Refunded` orders. To refund an already fully‑refunded order, or to refund an order in a status not listed above, use `WP Admin → WooCommerce → Orders`. ## The Refund Form[​](#the-refund-form "Direct link to The Refund Form") At the top of the modal you'll see two figures: * **Total** — the order total. * **Previously Refunded** — the sum of any refunds already issued against this order (shown as a negative amount). Only appears when there is at least one prior refund. Below that is the line items table: | Column | What it shows | | ----------------- | ----------------------------------------------------------------------------------- | | **Product** | The line item name | | **Price** | Unit price (tax‑inclusive or tax‑exclusive, depending on your store setting) | | **Qty** | The remaining refundable quantity (purchased qty minus any previously refunded qty) | | **Refund Qty** | Editable — how many units of this line you want to refund now | | **Refund Amount** | Auto‑calculated from Refund Qty × unit price, including the line's prorated tax | Below the table: * **Custom Amount** — an optional extra amount to add to the refund (for example, refunding a fee that isn't tied to a specific line item). Leave it blank if you don't need it. * **Reason** — an optional note that's saved on the refund record and appears in WooCommerce's order notes. * **Refund destination** — a radio group (see below). * **Refund Total** — the grand total of the refund, recalculated live as you type. ### Refunding Whole vs. Partial Quantities[​](#refunding-whole-vs-partial-quantities "Direct link to Refunding Whole vs. Partial Quantities") There's no separate "full refund" mode — set the Refund Qty for every line to its full remaining quantity to refund the whole order, or set it on just one or two lines for a partial refund. The **Process Refund** button is disabled until **Refund Total** is greater than zero and within the remaining refundable amount. ## Refund Destination[​](#refund-destination "Direct link to Refund Destination") For orders paid with anything other than the built‑in **POS Cash** gateway, the form asks where the refund should go: * **Refund to *(gateway name)*** — the gateway processes the refund through its own provider API. For Stripe Terminal this returns the funds to the original card; for Vipps MobilePay it issues a Vipps refund; and so on. This option only appears for gateways that advertise refund support to the POS — if your gateway doesn't, the option is disabled with the message *"Original payment method refunds are unavailable for this order."* * **Refund via cash** — record the refund as cash returned from the till, regardless of how the order was originally paid. The cashier physically hands the money over; WooCommerce records the refund but does not call any gateway. For orders paid with **POS Cash**, the radio group is hidden — cash is the only sensible destination, so it's used automatically. If WCPOS can't reach the gateway to check refund support, you'll see *"Couldn't verify original payment method refunds. Cash refunds are still available."* — you can still issue a cash refund. ### When to Use Cash vs. Original Method[​](#when-to-use-cash-vs-original-method "Direct link to When to Use Cash vs. Original Method") | Situation | Recommended destination | | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | | Card payment via Stripe Terminal / Vipps / etc., customer present and wants the money back on their card | **Refund to *(gateway)*** | | Card payment but customer prefers cash back (and you're allowed to do that) | **Refund via cash** | | Cash sale | **Refund via cash** (automatic; no choice shown) | | Manual card terminal (the gateway can't refund automatically) | **Refund via cash**, then refund manually on your standalone terminal | ## Confirming and Submitting[​](#confirming-and-submitting "Direct link to Confirming and Submitting") When you press **Process Refund**, a confirmation dialog asks *"Refund *(amount)* for Order #*(number)*?"*. Confirming triggers the refund: 1. WCPOS sends the refund to your WooCommerce store. 2. For gateway refunds, WooCommerce hands off to the gateway plugin to process the refund against the provider (Stripe, Vipps, etc.). 3. The order is refreshed locally so the new refund appears immediately. 4. A success toast confirms *"Refund of *(amount)* processed"*. If the gateway rejects the refund (declined card, expired authorization, network error, etc.), an error toast shows the gateway's message. The refund won't be recorded in WooCommerce in that case — you can adjust the form and try again, or fall back to a cash refund. ## After the Refund[​](#after-the-refund "Direct link to After the Refund") * **Partial refund** — the order keeps its existing status (Completed, etc.), and the order view modal shows a **Partially refunded** pill plus a `−(amount) refund` line in the hero subtitle. * **Full refund** — WooCommerce sets the order status to **Refunded**. * **Receipts** — when viewing the receipt for a refunded order, switching to **Live** mode shows the refund reflected in the totals (`Refunded -X` and `Net Total Y` rows on detailed receipts). **Fiscal** mode still shows the original payment‑complete snapshot, untouched — that's what fiscal mode is for. * **Cashier and store audit** — every POS refund is tagged with the cashier (`_pos_user`) and store (`_pos_store`) that issued it, so refunds appear under the right cashier and store in reporting. ## Things to Know[​](#things-to-know "Direct link to Things to Know") * **Coupons + refunds:** orders that used a coupon can still be refunded from the POS, but if you need to adjust how the coupon is recalculated against the refund, use `WP Admin → WooCommerce → Orders`. * **Negative quantities are not supported.** Older versions (v0.4.x) let you add a line with a negative quantity to record a return — this no longer works in v1.x. Use the Refund flow instead. * **Refunds require a server connection.** Unlike checkout, you can't queue a refund offline — the gateway and your store both need to be reachable. * **Issuing additional refunds on a fully‑refunded order** must be done from `WP Admin → WooCommerce → Orders`. ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [OrdersFind, filter, and manage your POS orders](/orders/.md) [Payment GatewaysWhich gateways support refunds back to the original method](/payment/.md) [ReceiptsFiscal vs. live receipts on refunded orders](/receipts/at-checkout.md) --- # Payment Methods WCPOS supports multiple payment methods to accommodate different business needs. The checkout uses an iframe/webview to load the WooCommerce Order Pay page, which means any payment gateway that works with WooCommerce can work in the POS. ## Default Payment Methods[​](#default-payment-methods "Direct link to Default Payment Methods") The free version includes two built-in payment gateways: ### Cash[​](#cash "Direct link to Cash") * Enter amount tendered * Automatic change calculation * No additional configuration required ### Card[​](#card "Direct link to Card") * For use with external card terminals * Simply mark the payment as complete after processing on your terminal * No direct integration required ## Additional Payment Gateways (Pro)[​](#additional-payment-gateways-pro "Direct link to Additional Payment Gateways (Pro)") Pro Feature Additional payment gateways require [WCPOS Pro](/getting-started/pro-license.md). With Pro, you can enable additional WooCommerce payment gateways in the POS checkout: * **Stripe Terminal** - Direct integration with Stripe card readers * **SumUp Terminal** - Integration with SumUp card readers * **Any WooCommerce Gateway** - Enable any gateway installed on your store ## Enabling and Disabling Gateways[​](#enabling-and-disabling-gateways "Direct link to Enabling and Disabling Gateways") Payment gateways are managed in the WordPress admin: 1. Go to `WP Admin > POS > Settings > Checkout` 2. You'll see a list of all installed WooCommerce payment gateways 3. Toggle each gateway on or off for the POS independently of your online store 4. Drag to reorder — the first enabled gateway becomes the default at checkout This means a gateway can be active on your website but disabled in the POS, or vice versa. See [Checkout Settings](/settings/wp-admin/checkout.md) for full details. ## Testing Payments[​](#testing-payments "Direct link to Testing Payments") Before going live with a new gateway: 1. **Cash gateway** — always available for testing the checkout flow without real transactions. 2. **Stripe Terminal** — Stripe provides a [simulated reader](https://docs.stripe.com/terminal/testing) for test mode. Enable test mode in your Stripe dashboard first. 3. **Third-party gateways** — check the gateway's own documentation for sandbox/test mode instructions. Most WooCommerce gateways support a test mode toggle. tip If a newly enabled gateway doesn't appear at checkout, try refreshing the POS. Gateway changes in WP Admin take effect on the next page load. ## Common Issues[​](#common-issues "Direct link to Common Issues") ### Gateway Not Appearing at Checkout[​](#gateway-not-appearing-at-checkout "Direct link to Gateway Not Appearing at Checkout") * Confirm the gateway is enabled for POS in `WP Admin > POS > Settings > Checkout`. * Check that the gateway is also enabled in `WP Admin > WooCommerce > Settings > Payments` — a gateway must be active in WooCommerce before it can appear in the POS. * Refresh the POS after making changes. ### Gateway Displays Incorrectly[​](#gateway-displays-incorrectly "Direct link to Gateway Displays Incorrectly") The checkout iframe loads your site's theme styles, which can sometimes interfere. Use the **Checkout Settings** button in the checkout modal to selectively disable styles or scripts. See [Checkout Troubleshooting](/pos/checkout/.md#checkout-settings-troubleshooting) for details. ### Payment Processing Fails[​](#payment-processing-fails "Direct link to Payment Processing Fails") * Check your site's error logs (`WP Admin > POS > Support > Logs`) for gateway-specific errors. * Ensure your SSL certificate is valid — most payment gateways require HTTPS. * If using a staging or local environment, confirm the gateway supports test/sandbox mode. ## Custom Gateways[​](#custom-gateways "Direct link to Custom Gateways") Create your own payment integrations using the [Custom Gateways](/payment/gateways/.md) system. [Gateways8 items](/payment/gateways/.md) --- # Payment Gateways WCPOS supports several custom payment gateways that extend the functionality of your Point of Sale system. These gateways are designed specifically for POS environments and provide seamless integration with various payment methods and services. ## Available Custom Gateways[​](#available-custom-gateways "Direct link to Available Custom Gateways") ### Hardware Terminal Gateways[​](#hardware-terminal-gateways "Direct link to Hardware Terminal Gateways") * **[Stripe Terminal](/payment/gateways/stripe-terminal.md)** - Accept payments using Stripe Terminal hardware readers * **[SumUp Terminal](/payment/gateways/sumup-terminal.md)** - Process payments through SumUp card readers * **[Square Terminal](/payment/gateways/square-terminal.md)** - Collect in-person payments on Square Terminal devices * **[PayPal Reader (Zettle)](/payment/gateways/paypal-reader.md)** - Take in-person card payments on a PayPal Reader (Zettle) terminal * **[Mollie Terminal](/payment/gateways/mollie-terminal.md)** - Take in-person payments on Mollie Terminal devices ### Mobile Payment Gateways[​](#mobile-payment-gateways "Direct link to Mobile Payment Gateways") * **[Vipps MobilePay](/payment/gateways/vipps-mobilepay.md)** - Accept phone-based payments via QR code or push notification ### Digital Payment Gateways[​](#digital-payment-gateways "Direct link to Digital Payment Gateways") * **[Email Invoice](/payment/gateways/email-invoice.md)** - Send payment invoices to customers via email * **[Web Checkout](/payment/gateways/web-checkout.md)** - Redirect customers to complete payments online ## Creating Your Own Gateway[​](#creating-your-own-gateway "Direct link to Creating Your Own Gateway") If you need a custom payment gateway for your specific requirements, you can use our **[Gateway Template](/reference/gateway-template.md)** to create your own WCPOS payment gateway. ## Installation Overview[​](#installation-overview "Direct link to Installation Overview") All custom gateways follow a similar installation process: 1. **Download** the latest release from the respective GitHub repository 2. **Install** the plugin via `WP Admin > Plugins > Add New > Upload Plugin` 3. **Configure** the gateway settings in `WP Admin > WooCommerce > Settings > Payments` 4. **Enable** the gateway in `WP Admin > POS > Settings > Checkout` ## Requirements[​](#requirements "Direct link to Requirements") WCPOS : Pro version required for POS checkout WordPress : WordPress with WooCommerce installed API Credentials : Appropriate API keys or credentials for the specific payment service ## Support[​](#support "Direct link to Support") For issues with custom gateways, please visit the respective GitHub repository and create an issue with detailed information about your problem. --- # Email Invoice Gateway The Email Invoice gateway allows you to send payment invoices to customers via email directly from WCPOS. This is perfect for situations where customers prefer to pay later or need to complete payment online using your web store's payment methods. ## Features[​](#features "Direct link to Features") #### Email Integration Send invoices directly from the POS interface #### Customer Management Auto-populate email from existing customer data or add new addresses #### Online Payment Customers receive a "Pay for this order" link to complete payment online #### Flexible Workflow Complete orders in-store or allow remote payment completion ## Installation[​](#installation "Direct link to Installation") 1 #### Install Email Invoice Gateway Install from `WP Admin > POS > Settings > Extensions`, or download the latest **plugin zip asset** (not the GitHub source-code zip or tarball) from the [GitHub releases page](https://github.com/wcpos/email-invoice-gateway/releases) and upload it via `Plugins > Add New > Upload Plugin`. 2 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **WCPOS Invoice Payment Gateway** in the list 3. Enable the gateway for use in the POS 4. Save your settings note This gateway doesn't require additional API keys or external service configuration. It uses your existing WordPress email system and WooCommerce payment methods. ## Usage[​](#usage "Direct link to Usage") ### Sending Invoices[​](#sending-invoices "Direct link to Sending Invoices") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "Email Invoice" as the payment method 3. **Email Address**: * For existing customers: Email is automatically populated from customer data * For guest orders: Enter the customer's email address manually 4. **Optional**: Check "Save to billing address" to update the customer's billing information 5. **Send Invoice**: Complete the process to send the invoice email ### Customer Experience[​](#customer-experience "Direct link to Customer Experience") When you send an invoice, the customer receives an email containing: * **Order Details**: Complete breakdown of items, quantities, and prices * **Order Total**: Final amount due including taxes and fees * **Payment Link**: Direct link to complete payment online * **Order Information**: Order number and reference details ### Payment Completion[​](#payment-completion "Direct link to Payment Completion") Customers can complete payment in two ways: 1. **Online Payment**: Click the "Pay for this order" link in the email 2. **In-Store Return**: Return to complete payment using other POS payment methods The "Pay for this order" link takes customers to a dedicated payment page on your website where they can use any of your enabled web payment gateways (Stripe, PayPal, etc.). ## Email Management[​](#email-management "Direct link to Email Management") ### Existing Customers[​](#existing-customers "Direct link to Existing Customers") * Email addresses are automatically retrieved from customer profiles * Customer billing information is preserved * Order history is maintained under the customer account ### Guest Customers[​](#guest-customers "Direct link to Guest Customers") * Manually enter email addresses for one-time customers * Option to save email to billing address for future reference * Guest orders are properly tracked in WooCommerce ### Email Templates[​](#email-templates "Direct link to Email Templates") The gateway uses WooCommerce's standard email templates: * **Customisable**: Modify email appearance through WooCommerce email settings * **Branded**: Include your store logo and branding * **Professional**: Clean, professional invoice format * **Mobile-Friendly**: Responsive design for all devices ## Use Cases[​](#use-cases "Direct link to Use Cases") ### Perfect For[​](#perfect-for "Direct link to Perfect For") * **B2B Sales**: Business customers who need to process payments through their accounting systems * **Large Orders**: High-value transactions that require approval or processing time * **Remote Customers**: Customers who need to complete payment after leaving the store * **Account Customers**: Regular customers with established payment terms * **Quote-to-Order**: Converting quotes or estimates into payable invoices ### Workflow Examples[​](#workflow-examples "Direct link to Workflow Examples") #### Retail Store 1. Customer selects items but needs to get approval for purchase 2. Send invoice email with all details 3. Customer completes payment online when ready 4. Order automatically updates in your system #### Service Business 1. Complete service work and add items to POS 2. Send invoice to customer's accounting department 3. Customer pays online using preferred payment method 4. Receive payment confirmation and complete order ## Requirements[​](#requirements "Direct link to Requirements") WCPOS : Pro version required for POS checkout Email System : Working WordPress email configuration Web Payment Gateways : At least one online payment method enabled in WooCommerce SSL Certificate : HTTPS required for secure payment processing ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### Common Issues[​](#common-issues "Direct link to Common Issues") Emails not sending * Check WordPress email configuration * Verify SMTP settings if using custom email service * Test with WordPress email testing plugins * Check spam folders for test emails Payment links not working * Ensure WooCommerce is properly configured * Verify at least one payment gateway is enabled for web checkout * Check that SSL certificate is properly installed * Confirm order status allows payment Customer can't complete payment * Verify web payment gateways are active and configured * Check that the order hasn't expired or been cancelled * Ensure customer has sufficient payment method limits * Test the payment process yourself ### Email Delivery[​](#email-delivery "Direct link to Email Delivery") For reliable email delivery, consider: * **SMTP Service**: Use services like SendGrid, Mailgun, or Amazon SES * **Email Plugins**: Install WordPress SMTP plugins for better delivery * **Domain Authentication**: Set up SPF, DKIM, and DMARC records * **Monitoring**: Track email delivery and open rates ### Getting Help[​](#getting-help "Direct link to Getting Help") For technical support: * Visit the [GitHub repository](https://github.com/wcpos/email-invoice-gateway) to report issues * Check WooCommerce email documentation for template customisation * Test email functionality with WordPress email testing tools ## Screenshots[​](#screenshots "Direct link to Screenshots") Screenshots will be added in a future update to show: * Email address entry interface in the POS * Professional invoice email template with order details * Customer payment completion on the web store --- # Mollie Terminal Gateway The Mollie Terminal gateway lets you take in-person payments on [Mollie Terminal](https://www.mollie.com/products/point-of-sale) hardware directly from WCPOS. A payment is started from WooCommerce and completed on the terminal, and Mollie's confirmation is written back to the order. ## Features[​](#features "Direct link to Features") #### Hardware Integration Send payments to Mollie terminals registered on your Mollie account and collect card-present payments #### No Manual Pairing Terminals are fetched live from your Mollie account — pick one from a dropdown, no device ID to paste #### Reliable Completion Payments are confirmed by polling Mollie, and the POS redirects to the receipt automatically once the terminal confirms #### Secure Transactions PCI-compliant, card-present processing handled on Mollie hardware #### Refunds Supported Refund from the WooCommerce order screen, reconciled against Mollie so refunds are never duplicated ## How It Works[​](#how-it-works "Direct link to How It Works") Mollie Terminal uses Mollie's **server-side `pointofsale` payments**. When you start a payment, WooCommerce creates a Mollie payment for the order and Mollie pushes it to the selected terminal. The customer pays on the device, and **Mollie is the source of truth** for payment and refund state — the local WooCommerce order meta is only a cache. **How a payment is confirmed.** While the payment is in progress the POS polls Mollie (every 2 seconds by default) and, when the terminal confirms, redirects straight to the thank-you page. Mollie webhooks are also used to speed this up — and the webhook URL is set automatically on every payment, so there is **nothing to configure in the Mollie dashboard**. The terminal must be registered and active on the same Mollie account as the plugin. ## Setup[​](#setup "Direct link to Setup") 1 #### Install Mollie Terminal for WooCommerce Install from `WP Admin > POS > Settings > Extensions`, or download the latest **plugin zip asset** (not the GitHub source-code zip or tarball) from the [GitHub releases page](https://github.com/wcpos/mollie-terminal-for-woocommerce/releases) and upload it via `Plugins > Add New > Upload Plugin`. 2 #### Configure your Mollie credentials 1. Go to `WP Admin > WooCommerce > Settings > Payments` and open **Mollie Terminal** 2. Set **Mode** to `Live` — terminal payments require a live account (see [Scope & Limitations](#scope-and-limitations)) 3. Set **API key source** to reuse the key from the official Mollie Payments for WooCommerce plugin, or use the key entered on this screen 4. If you enter the key here, paste your Mollie **live API key** into **Mollie API Key** 5. Save Use Live mode Mollie terminals exist only on **live** accounts, so the test API key cannot drive a terminal. The settings screen warns you when Test mode is selected — switch to `Live` with your live API key to take payments. See [Scope & Limitations](#scope-and-limitations). No Profile ID needed `pointofsale` payments do not require a Mollie **Profile ID**, and terminals are listed across the whole account, so there is nothing else to paste. 3 #### Choose your terminals 1. Pick a **Default terminal** from the dropdown. The list is fetched from the selected Mollie environment — inactive terminals are hidden, because Mollie cannot reactivate them. 2. *(Optional)* Restrict **Enabled terminals** to the devices actually in use. The saved default remains available even if it is not selected here; leave the setting empty to allow all active terminals. To retire a terminal, also change or clear **Default terminal**. 3. *(Optional)* Enable **Lock terminal selection** so cashiers cannot change the terminal at checkout — the default terminal is always used, and this is enforced on the server too. 4. Save 4 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **Mollie Terminal** gateway and enable it for the POS 3. Save your settings note The **Enable/Disable** checkbox on the WooCommerce settings screen controls the *online store* checkout only. WCPOS uses this gateway once it is configured, whether or not that box is ticked. ## Settings reference[​](#settings "Direct link to Settings reference") | Setting | What it does | | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Enable/Disable** | Enables the gateway for the online store checkout (not required for POS) | | **Title** / **Description** | Label and text shown to the customer at checkout | | **Mode** | `Test` or `Live`. Terminal payments require **Live** — the test API key cannot drive a terminal | | **API key source** | Uses the key entered below, or reuses the matching test/live key from the official Mollie Payments for WooCommerce plugin. If the shared key is unavailable, the plugin falls back to the key below | | **Mollie API Key** | The test or live API key for the selected mode. Used when **API key source** is set to the key entered here, and as the fallback for a missing shared key | | **Default terminal** | The terminal used by default at checkout, chosen from a dropdown of active terminals in the selected Mollie environment | | **Enabled terminals** | Restricts the checkout list to selected terminals. Empty = all active terminals. The saved default is always available, so change or clear it too when retiring a terminal | | **Lock terminal selection** | Forces the default terminal at checkout so cashiers cannot change it (requires a default terminal) | | **Checkout debug logs** | Shows the **Show logs**, **Copy**, and **Clear** tools on the checkout payment panel. Leave this off unless gathering logs for support; payment activity is always recorded under `WooCommerce > Status > Logs` | The webhook URL is applied automatically on every payment, so there is no webhook field to fill in and no Mollie dashboard configuration required. ## Usage[​](#usage "Direct link to Usage") ### Processing Payments[​](#processing-payments "Direct link to Processing Payments") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "Mollie Terminal" as the payment method 3. **Choose Terminal**: Pick a terminal from the dropdown (defaults to the configured one; hidden if terminal selection is locked) 4. **Start Payment**: Click **Start Terminal Payment** — Mollie pushes the payment to the device 5. **Customer Payment**: The customer taps, inserts, or swipes their card on the terminal. The status updates live — `Sending to terminal…` → `Waiting for terminal…` 6. **Automatic Completion**: When the terminal confirms, the order is marked paid and the POS redirects to the receipt automatically ### Payment Controls[​](#payment-controls "Direct link to Payment Controls") * **Start Terminal Payment**: Send a new payment request to the selected terminal * **Cancel Payment**: Cancel a payment that is still open. Once the payment has reached the terminal Mollie reports it as no longer cancelable, and the cashier cancels on the device itself ### Order Management[​](#order-management "Direct link to Order Management") * **Verified completion**: Every webhook, poll, cancel, and retry fetches authoritative Mollie state before changing an order, so orders are marked paid only on confirmed Mollie state * **Payment Tracking**: Payment attempts are recorded as append-only history on the order * **Receipt Generation**: Standard POS receipts are generated after successful payments ## Refunds[​](#refunds "Direct link to Refunds") Refunds are supported. Refund an order from the normal WooCommerce order screen and the refund is sent to Mollie. Because Mollie is the source of truth, refund retries reconcile against Mollie's refund IDs and metadata **before** creating another refund, so a refund is never accidentally issued twice. ## Stale payment cleanup[​](#stale-payment-cleanup "Direct link to Stale payment cleanup") A Mollie `pointofsale` payment can stay "open" on Mollie's side if a checkout is abandoned. The plugin cancels these open payments automatically when: * the auto-poll times out (5 minutes by default) — the cancel is sent instead of leaving the payment behind * the order is completed with a **different** payment method (for example the customer pays cash instead), or the order is cancelled in WooCommerce * the checkout page is closed mid-payment — a best-effort cancel fires as the tab leaves * a WP-Cron sweep runs every 10 minutes and cancels or resolves payments left open past the stale threshold (10 minutes by default), including when the browser closes or the network drops before the other cleanup paths run If the payment already reached the terminal, Mollie reports it as not cancelable and the cashier cancels on the device itself — these cleanups are safe no-ops in that case. ## Requirements[​](#requirements "Direct link to Requirements") Mollie Account : Active Mollie account with a live API key Compatible Hardware : A Mollie Terminal device, active on that Mollie account Currency : EUR — POS terminal payments are limited to EUR for now WCPOS : Pro version required for POS checkout Stable Connection : Reliable internet connection for API communication ## Scope & Limitations[​](#scope-and-limitations "Direct link to Scope & Limitations") Test mode limitation Mollie terminals exist only on **live** accounts. The Mollie **test** API key cannot drive a physical (or iOS/Android) terminal, so terminal payments cannot be exercised end-to-end in test mode. This is a Mollie platform limitation, not a plugin restriction — the settings screen shows a warning when Test mode is selected. Use **Live** mode with your live API key to take terminal payments. Currency POS terminal payments are limited to **EUR** until broader Mollie Terminal currency support is confirmed. ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### Common Issues[​](#common-issues "Direct link to Common Issues") No terminals appear in the dropdown * Confirm **Mode** is set to `Live` and the effective API key is a live key — terminals do not exist on test accounts * Check the terminal is registered and **active** on your Mollie account; inactive terminals are hidden because Mollie cannot reactivate them * Make sure your site can reach Mollie — the list is fetched live over the API Payment won't start * Confirm a terminal is selected (or a **Default terminal** is set when selection is locked) * Check the terminal is powered on, online, and active on the same Mollie account * Verify the order currency is **EUR** The terminal timed out or the payment stayed open * The plugin attempts to cancel open payments automatically on timeout (5 minutes by default) * If the payment already reached the terminal and cannot be cancelled automatically, cancel it on the device itself * You can then start a fresh payment or take payment another way Order completed on the terminal but is slow to update * The POS polls Mollie every 2 seconds and redirects when the payment confirms; a webhook usually confirms it first * Because Mollie is the source of truth, the order is reconciled against authoritative Mollie state — it is not lost * Check `WooCommerce > Status > Logs` for any Mollie API messages ### Getting Help[​](#getting-help "Direct link to Getting Help") For technical support: * Visit the [GitHub repository](https://github.com/wcpos/mollie-terminal-for-woocommerce) to report issues * Check the [Mollie Terminal setup guide](https://docs.mollie.com/docs/setting-up-terminal) and the [Mollie Create Payment API](https://docs.mollie.com/reference/create-payment) for API-related questions * Contact Mollie support for account and hardware issues ## Screenshots[​](#screenshots "Direct link to Screenshots") Screenshots will be added in a future update to show: * The Mollie Terminal settings screen — API key, default terminal, and enabled terminals * Gateway enablement in WCPOS settings * Payment processing workflow in the POS checkout --- # PayPal Reader (Zettle) Gateway The PayPal Reader gateway lets you accept in-person card payments using a **PayPal Reader (Zettle)** card terminal directly from WCPOS. The browser streams the live payment status from the reader over a secure connection to Zettle's Reader Connect API, so the cashier sees each step of the payment as it happens. ## Features[​](#features "Direct link to Features") #### In-person card payments Take chip, contactless, and mobile-wallet payments on a PayPal Reader (Zettle) terminal #### Live payment status The POS shows real-time progress — connecting, payment in progress, completed, or cancelled #### Amount verified server-side The reported amount is always checked against the order total before the order is placed #### Simple pairing Link a reader from the gateway settings using a pairing code shown on the device ## Requirements[​](#requirements "Direct link to Requirements") WCPOS : Pro version required for POS checkout WordPress : WordPress 5.2+ with WooCommerce active PHP : PHP 7.4 or higher Zettle account : A Zettle developer merchant account, plus a Zettle Client ID and Assertion (JWT) from the Zettle Developer Portal Compatible hardware : A PayPal Reader (Zettle) card terminal Stable connection : Live payments stream status to the reader over the network and require an internet connection Supported hardware and regions PayPal Reader / Zettle availability, supported reader models, and supported countries are determined by your **Zettle merchant account**, not by WCPOS. Confirm your reader and region are supported with PayPal/Zettle before purchasing. ## Installation[​](#installation "Direct link to Installation") 1 #### Install PayPal Reader for WooCommerce Install from `WP Admin > POS > Settings > Extensions`, or download the latest **plugin zip asset** (not the GitHub source-code zip or tarball) from the [GitHub releases page](https://github.com/wcpos/paypal-reader-for-woocommerce/releases) and upload it via `Plugins > Add New > Upload Plugin`. WooCommerce must be installed and active. 2 #### Configure the gateway 1. Navigate to `WP Admin > WooCommerce > Settings > Payments` 2. Find **PayPal Reader** in the payment methods list and open its settings 3. Leave **Enable Test mode** on while you verify the setup. Use the credentials from your Zettle developer merchant account in test mode; disable it later to take live payments 4. Enter your **Zettle Client ID** — your Zettle OAuth client ID from the Zettle Developer Portal 5. Enter your **Zettle Assertion** — your Zettle OAuth assertion (JWT). This is treated as a secret 6. Optionally set the **Title** and **Description** shown to customers 7. **Save** the settings note The **"Enable PayPal Reader for web checkout"** checkbox is for your online store's checkout only — it is **not required for the POS**. You enable the gateway for the POS in a later step. 3 #### Pair your reader 1. After saving, scroll to the **Paired readers** section at the bottom of the settings screen (it appears once your Client ID and Assertion are saved) 2. On the PayPal Reader device, open **Settings → Link with a developer** to display the pairing code 3. Under **Pair a new reader**, enter the **Pairing code** and optionally a **Reader name** (e.g. "Front counter") 4. Click **Pair reader**. The reader appears in the paired list and is ready to take payments Important A reader must be successfully paired before you can take payments. Use **Unpair** on the paired list to remove a reader. 4 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **PayPal Reader** gateway in the list 3. Enable it for use in the POS 4. Save your settings ## Taking a payment[​](#taking-a-payment "Direct link to Taking a payment") 1. **Add items** to the cart in the POS and proceed to checkout 2. **Select PayPal Reader** as the payment method 3. **Choose a paired reader** and start the payment. (If none are paired, you'll be prompted to ask the store admin to pair one in `WooCommerce → Settings → Payments → PayPal Reader`.) 4. The POS shows live status as it connects: *"Connecting to reader…"*, *"Reader ready. Requesting payment…"*, *"Payment in progress…"* 5. The customer taps or inserts their card on the reader 6. On success, the amount is verified against the order total, the transaction reference is recorded, and the order is placed automatically 7. Use **Cancel payment** at any point to cancel the request on the reader ## Going live[​](#going-live "Direct link to Going live") When you've verified everything in test mode: 1. Disable **Enable Test mode** 2. Replace your Zettle test credentials with your **production** Client ID and Assertion 3. Save — the endpoints and flow are identical; only the merchant account differs ## Requirements recap & limitations[​](#limitations "Direct link to Requirements recap & limitations") * **The order is only completed after a confirmed reader result.** WCPOS will not place the order unless the payment reports as completed. * **Amount-mismatch protection.** If the amount the reader reports doesn't match the order total, the payment is refused — so avoid editing the cart total mid-payment. * **Connectivity.** Live payments depend on the browser maintaining a session to Zettle's Reader Connect API; a stable internet connection is required. ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") The Paired readers section isn't showing Save your **Zettle Client ID** and **Assertion** first. The pairing panel only appears once both credentials are saved. You'll otherwise see *"Save your Zettle Client ID and Assertion above before pairing a reader."* Reader won't pair * On the reader, make sure you opened **Settings → Link with a developer** to get a fresh pairing code * Enter the code exactly as shown, before it expires * Confirm your Zettle Client ID and Assertion are correct and saved * Ensure the reader and your network have a stable internet connection Payment is refused with an amount mismatch The plugin verifies the reader-reported amount against the order total and refuses any mismatch. Don't change the cart or order total while a payment is in progress — cancel the payment, adjust the cart, then start a new payment. No real payments are processed / an admin warning about a 'mock reader' appears A development/CI constant (`PRWC_USE_MOCK_READER`) is defined in `wp-config.php`. Remove that constant before taking live payments — while it's set, no real payments are processed. ### Getting help[​](#getting-help "Direct link to Getting help") * Report gateway issues on the [GitHub repository](https://github.com/wcpos/paypal-reader-for-woocommerce) * Contact PayPal/Zettle support for account, reader hardware, and regional availability questions --- # Square Terminal Gateway The Square Terminal gateway lets you collect WooCommerce order payments on [Square Terminal](https://squareup.com/hardware/terminal) hardware directly from WCPOS. A payment is requested from WooCommerce and completed on a paired Square Terminal device, and the result is written back to the order. ## Features[​](#features "Direct link to Features") #### Hardware Integration Send payments to paired Square Terminal devices and collect card-present payments #### One-Click Connect Authorize with Square directly — no access token to create or paste #### Reliable Completion Payments are confirmed by polling and a background sweeper, with webhooks to speed it up #### Secure Transactions PCI-compliant, card-present processing handled on Square hardware #### Sandbox & Production Validate against the Square Sandbox before switching to live payments ## How It Works[​](#how-it-works "Direct link to How It Works") Unlike browser-SDK gateways, Square Terminal uses Square's **server-side Terminal API**. When you start a payment, WooCommerce creates a Terminal Checkout for the order and Square pushes it to the paired device. The customer pays on the terminal, and the result is written back to the order. **How a payment is confirmed.** The POS polls Square while the payment is in progress, and a background sweeper reconciles anything the poll misses — a closed browser tab, for example. Square webhooks are an *optional* addition that shortens the wait; they are not required, and a site without them never loses a payment. The Square Terminal device must be online and signed in to the same Square account and location as the plugin. ## Setup[​](#setup "Direct link to Setup") 1 #### Install Square Terminal for WooCommerce Install from `WP Admin > POS > Settings > Extensions`, or download the latest **plugin zip asset** (not the GitHub source-code zip or tarball) from the [GitHub releases page](https://github.com/wcpos/square-terminal-for-woocommerce/releases) and upload it via `Plugins > Add New > Upload Plugin`. 2 #### Connect to Square 1. Go to `WP Admin > WooCommerce > Settings > Payments` and open **Square Terminal** 2. Under **Square account**, choose the **Environment** — `Sandbox` for testing, `Production` for live payments 3. Click **Connect to Square** and approve the permissions Square shows you 4. Choose the **Location ID** — the Square location the Terminal takes payments for Choose the environment **before** connecting. A connection covers one environment only; a sandbox connection can never authorize production payments. Already using the official WooCommerce Square plugin? Environment and Location ID are pre-filled from its settings. Only those two values are read — no credentials are shared between the plugins, and you still need to connect or supply an access token here. Prefer to use your own access token? Open **Advanced settings** and paste an access token for the selected environment instead of connecting. Everything else works identically. 3 #### Pair your Square Terminal Under **Terminal**: 1. Click **Create Device Code** — a pairing code appears 2. On the Square Terminal, open the device-code sign-in screen and enter the code. If the Terminal is currently signed in to Square POS or another integration, sign out of that first — the device-code screen is not reachable while it is in use elsewhere. 3. Click **Check for readers** to confirm it now appears under *Paired with this plugin* An empty list before pairing is expected, not a fault. Square's device API only reports Terminals that have been set up for **Terminal API** use — a Terminal running Square POS does not appear at all until a device code is entered on it. 4 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **Square Terminal** gateway and enable it for the POS 3. Save your settings note The **Enable/Disable** checkbox on the WooCommerce settings screen controls the *online store* checkout only. WCPOS uses this gateway automatically once it is configured, whether or not that box is ticked. ## Pairing a Terminal[​](#pairing "Direct link to Pairing a Terminal") A Square Terminal has to be paired with **this plugin** before a cashier can select it. Pairing creates a Terminal API *Device Code*, and that is the only way the plugin can address the device. Under **Terminal** on the settings screen: * **Create Device Code** — generates a code to enter on the Terminal. It is short-lived; generate a fresh one if it expires. * **Check for readers** — lists what Square can see, in two groups: * **Paired with this plugin** — selectable at checkout * **Other devices Square can see at this location** — set up by another application, so not selectable here until paired with this plugin * **Validate Settings** — checks the credentials and location against Square Why a Terminal you own might not be selectable Device Codes belong to the application that created them, so a Terminal set up by another Terminal API integration appears under *Other devices Square can see* but cannot be selected here. A Terminal running Square POS does not appear at all. Either way the fix is the same: sign the Terminal out of whatever it is currently paired to, then enter a fresh **Create Device Code** here. ## Webhooks[​](#webhooks "Direct link to Webhooks") Webhooks are **optional**. They shorten how long a payment takes to confirm. Polling and the background sweeper confirm every payment regardless, so a site without a webhook subscription still works correctly — just a little slower to settle. Not available if you used Connect to Square A webhook subscription belongs to a Square *application*, and adding one needs access to that application in the Square Developer Dashboard. If you connected with **Connect to Square** you are authorizing the WCPOS application rather than one of your own, so there is no dashboard for you to add a subscription in and no signature key for you to copy. Payments still confirm normally — by polling and the sweeper. The steps below apply only if you set the plugin up with **your own access token** under Advanced settings. To add one, using your own Square application: 1. On the settings screen, under **Terminal → Webhooks**, click **Copy** to copy the webhook URL 2. In the [Square Developer Dashboard](https://developer.squareup.com/apps), open your application and go to **Webhooks** 3. Add a subscription for the **`terminal.checkout.updated`** event, pasting that URL as the notification URL 4. Copy the **Webhook Signature Key** from Square into **Advanced settings** in the plugin The **Webhooks** row then reports whether a signature-verified webhook has arrived, and when. The URL must match exactly Square signs each webhook over the notification URL it was given. If the URL in Square differs from the plugin's by even a character, every delivery fails verification. Use the **Copy** button rather than typing it. Why this step is manual Square's Webhook Subscriptions API is scoped to the *application*, not to individual sellers, and [cannot be called with a seller access token](https://developer.squareup.com/docs/webhooks/webhook-subscriptions-api). The plugin therefore cannot create the subscription for you. ### If webhooks stop verifying[​](#webhook-troubleshooting "Direct link to If webhooks stop verifying") The **Webhooks** row shows *Not verified yet* when no webhook has arrived and verified under the **current** settings. If payments have already run, check in this order: 1. The **Webhook Signature Key** in Advanced settings matches the one in Square 2. The notification URL in Square matches the URL shown in the plugin, exactly 3. The `terminal.checkout.updated` event is subscribed 4. Your site is publicly reachable over HTTPS — check delivery attempts in the Square Dashboard Changing the environment, webhook URL, or signature key resets this row until the next webhook arrives. That is intended: a delivery verified under the old settings says nothing about the new ones. ## Settings reference[​](#settings "Direct link to Settings reference") The settings screen is ordered the way setup runs. | Section | Contains | | ---------------------- | ---------------------------------------------------------- | | **Square account** | Environment, **Connect to Square**, Location ID | | **Terminal** | Pairing controls, reader list, webhook status | | **Checkout behaviour** | Skip receipt screen, collect signature, debug logs | | **Advanced settings** | Access tokens, webhook signature key, webhook URL override | **Advanced settings** is collapsed by default. It holds the manual access tokens — needed only if you are not connecting — and the webhook signature key. The **Webhook URL override** should stay empty unless your public URL differs from the one the plugin derives, for example behind a proxy or custom domain. ## Usage[​](#usage "Direct link to Usage") ### Processing Payments[​](#processing-payments "Direct link to Processing Payments") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "Square Terminal" as the payment method 3. **Choose Device**: Pick the paired terminal from the **Terminal Device** list 4. **Start Payment**: Click **Start Payment** — Square pushes the checkout to the device 5. **Customer Payment**: The customer taps, inserts, or swipes their card on the Square Terminal 6. **Completion**: The status updates live while you wait, and the order is marked paid once Square confirms the payment In **Sandbox**, the device list contains Square's documented test device IDs, so every outcome — success, timeout, offline — can be exercised without hardware. ### Payment Controls[​](#payment-controls "Direct link to Payment Controls") * **Start Payment**: Send a new payment request to the selected terminal * **Cancel Payment**: Cancel a payment currently in progress on the terminal * **Check Status**: Ask Square for the current state immediately * **Release Payment**: Detach an unresponsive terminal so the order can be paid another way; the abandoned checkout is still reconciled in the background * **Payment Log**: An optional per-order log recording each Square step and outcome ### Order Management[​](#order-management "Direct link to Order Management") * **Verified completion**: Orders are marked paid only after the payment is verified against Square's Payment object — never on an unverified signal * **Payment Tracking**: Square identifiers and a payment log are stored on the order, and key steps are written to order notes * **Receipt Generation**: Standard POS receipts are generated after successful payments ## Requirements[​](#requirements "Direct link to Requirements") Square Account : Active Square seller account Square Location : A Square location, and its Location ID Compatible Hardware : A Square Terminal device, online and signed in to the same Square location Public HTTPS Site : Required only if you want webhooks; payments confirm by polling without them WCPOS : Pro version required for POS checkout ## Hardware Compatibility[​](#hardware-compatibility "Direct link to Hardware Compatibility") Connectivity Requirements Square Terminal uses Square's server-side Terminal API: the checkout is created by your site and delivered to the paired device by Square. The terminal must be online and signed in to the same Square account and location as the plugin. ### Supported Terminals[​](#supported-terminals "Direct link to Supported Terminals") * **Square Terminal** ✅ — Square's dedicated countertop card terminal ## Scope & Limitations[​](#scope-and-limitations "Direct link to Scope & Limitations") Current scope * Focused on **POS / order-pay** flows. Availability on the customer-facing storefront checkout is off by default and must be explicitly enabled. * **Collects payments only** — refunds are not yet supported. Square identifiers are stored on the order so refund support can be added later. * Webhook subscriptions must be added manually in Square; see [Webhooks](#webhooks). ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### Common Issues[​](#common-issues "Direct link to Common Issues") The Terminal Device list is empty * The Terminal has to be paired **with this plugin** first — use **Create Device Code** and enter the code on the device * A Terminal paired through the Square Dashboard or the Square POS app will not appear until it is paired here * Click **Check for readers**: if it appears under *Other devices Square can see*, it exists but is not paired with this plugin * Confirm the **Location ID** matches the location the Terminal is signed in to Device won't pair * Make sure you entered the Device Code before it expired — generate a fresh one with **Create Device Code** * Confirm the terminal is online and signed in to the same Square account and **Location ID** as the plugin * Check the **Environment** matches the account the terminal is signed in to Validate Settings fails * If connected, check the **Square account** row still shows *Connected to Square*; if it asks you to reconnect, the authorization lapsed * If using an access token, verify it matches the selected **Environment** — a Sandbox token will not work in Production, and vice versa * Confirm the **Location ID** belongs to that account Payment completes on the terminal but the order is slow to update * This is what webhooks fix. Without one, the order updates when polling or the background sweeper next reconciles it * Check the **Webhooks** row — if it says *Not verified yet* after payments have run, follow [If webhooks stop verifying](#webhook-troubleshooting) * The order is never lost: the sweeper reconciles any payment the poll misses Payment won't start * Confirm a terminal is selected and the device is paired and online * Check that the device is signed in to the configured **Location ID** * Review the **Payment Log** and `WooCommerce > Status > Logs` for Square API messages It says reconnection to Square is required Square authorizations are renewed automatically. If a renewal cannot complete, the plugin ends the authorization rather than leaving it in an unusable state, and the settings screen asks you to reconnect. Click **Reconnect to Square** — nothing else needs changing. ### Getting Help[​](#getting-help "Direct link to Getting Help") For technical support: * Visit the [GitHub repository](https://github.com/wcpos/square-terminal-for-woocommerce) to report issues * Check the [Square Terminal API documentation](https://developer.squareup.com/docs/terminal-api/overview) for hardware and API guidance * Contact Square support for account and hardware issues Logs are written to `WooCommerce > Status > Logs` under the `sqtwc` handle, and record each device lookup and webhook outcome. ## Screenshots[​](#screenshots "Direct link to Screenshots") Screenshots will be added in a future update to show: * The Square account, Terminal, and Advanced settings sections * Gateway enablement in WCPOS settings * Payment processing workflow in the POS checkout --- # Stripe Terminal Gateway The Stripe Terminal gateway allows you to accept in-person payments using Stripe Terminal hardware readers directly within WCPOS. This gateway supports both physical card readers and simulator mode for testing. ## Features[​](#features "Direct link to Features") #### Hardware Integration Connect physical Stripe Terminal readers via internet connection #### Simulator Mode Test payments without hardware using Stripe's simulator #### Real-time Processing Instant payment processing and confirmation #### Secure Transactions PCI-compliant payment processing through Stripe #### Phone Orders (MOTO) Accept card payments over the phone by keying details into the reader ## Installation[​](#installation "Direct link to Installation") 1 #### Install Stripe Terminal for WooCommerce Install from `WP Admin > POS > Settings > Extensions`, or download the latest **plugin zip asset** (not the GitHub source-code zip or tarball) from the [GitHub releases page](https://github.com/wcpos/stripe-terminal-for-woocommerce/releases) and upload it via `Plugins > Add New > Upload Plugin`. 2 #### Configure Stripe Settings 1. Navigate to `WP Admin > WooCommerce > Settings > Payments` 2. Find **Stripe Terminal** in the payment methods list 3. Click on **Stripe Terminal** to access settings 4. Enter your **Stripe Secret Key** (you can get this from your Stripe Dashboard) 5. Save the settings note You do not need to enable the Stripe Terminal gateway in WooCommerce settings. It will be enabled specifically for the POS in the next step. 3 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **Stripe Terminal** gateway in the list 3. Enable the gateway for use in the POS 4. Save your settings ## Usage[​](#usage "Direct link to Usage") ### Connecting a Reader[​](#connecting-a-reader "Direct link to Connecting a Reader") When you select the Stripe Terminal gateway during checkout in the POS: 1. **Choose Connection Method**: You can either connect a physical reader or use the simulator 2. **Physical Reader**: Follow the on-screen instructions to connect your Stripe Terminal device 3. **Simulator**: Select simulator mode to test various payment scenarios without hardware ### Processing Payments[​](#processing-payments "Direct link to Processing Payments") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "Stripe Terminal" as the payment method 3. **Connect Reader**: Connect your reader or choose simulator mode 4. **Process Payment**: Follow the prompts to complete the transaction 5. **Confirmation**: The order will be automatically completed upon successful payment ### Testing with Simulator[​](#testing-with-simulator "Direct link to Testing with Simulator") The simulator allows you to test various payment methods and scenarios: * **Card Payments**: Test different card types (Visa, Mastercard, etc.) * **Contactless Payments**: Simulate tap-to-pay transactions * **Error Scenarios**: Test declined payments and other error conditions * **Different Amounts**: Test various transaction amounts ### Phone Orders (MOTO)[​](#phone-orders-moto "Direct link to Phone Orders (MOTO)") MOTO (Mail Order/Telephone Order) lets you process card payments for customers who aren't physically present — for example, when taking an order over the phone. Instead of tapping or inserting a card, the merchant keys the card details directly into the terminal reader's screen. #### Setup[​](#setup "Direct link to Setup") 1 #### Request MOTO access from Stripe MOTO is not enabled by default. Contact [Stripe support](https://support.stripe.com/contact) and ask them to enable MOTO permissions for your account. This is a quick process but requires manual approval from Stripe. 2 #### Enable in plugin settings 1. Navigate to `WP Admin > WooCommerce > Settings > Payments > Stripe Terminal` 2. Check the **Phone Orders (MOTO)** checkbox 3. Save the settings 3 #### Connect a compatible reader MOTO only works with compatible internet-connected readers listed in [Supported Terminals](#supported-terminals-internet-connected). The toggle will not appear for other reader types. #### Taking a Phone Order[​](#taking-a-phone-order "Direct link to Taking a Phone Order") 1. Connect a compatible reader (see [Supported Terminals](#supported-terminals-internet-connected)) 2. At the payment screen, toggle **Phone Order** on 3. Click **Collect Card Payment** — the reader will display a card number entry screen instead of prompting for a tap/insert 4. Key in the customer's card number, expiry, and CVV on the reader 5. The payment processes as normal from there tip MOTO payments use `card` as the payment method type rather than `card_present`. This means they are treated more like online transactions from Stripe's perspective, so standard online card processing fees apply rather than in-person rates. caution The Phone Order toggle only appears when all three conditions are met: the MOTO setting is enabled in plugin settings, a compatible reader is connected, and the reader is not a simulator. If you don't see the toggle, check these conditions. ## Requirements[​](#requirements "Direct link to Requirements") Stripe Account : Active Stripe account with Terminal enabled API Keys : Stripe secret key from your dashboard WCPOS : Pro version required for POS checkout HTTPS : Your site must use SSL/HTTPS for security ## Hardware Compatibility[​](#hardware-compatibility "Direct link to Hardware Compatibility") Connectivity Requirements This implementation uses Stripe's JavaScript SDK, which means it works through web applications but requires **internet-connected terminals only**. Bluetooth terminals are not currently supported. ### Supported Terminals (Internet-Connected)[​](#supported-terminals-internet-connected "Direct link to Supported Terminals (Internet-Connected)") * **Stripe Reader S700/S710** ✅ - Ethernet/WiFi-connected terminal * **WisePOS E** ✅ - WiFi-connected terminal ### Unsupported Terminals (Bluetooth)[​](#unsupported-terminals-bluetooth "Direct link to Unsupported Terminals (Bluetooth)") * **BBPOS Chipper 2X BT** ❌ - Bluetooth only * **BBPOS WisePad 3** ❌ - Bluetooth only * **Verifone P400** ❌ - Bluetooth only Future Support Bluetooth terminal support is planned for a future iOS and Android app release. When available, this will enable support for all Stripe Terminal certified readers including the M2 and WisePad 3. ### Common Issues[​](#common-issues "Direct link to Common Issues") Reader won't connect * Ensure you're using a [supported internet-connected terminal](#supported-terminals-internet-connected) * Verify the terminal is connected to WiFi/Ethernet and online * Check that your Stripe account has Terminal enabled * Confirm the terminal is registered in your Stripe Dashboard Payment declined * Check that your Stripe account is active and in good standing * Verify the card being used is valid * Ensure sufficient funds are available Phone Order toggle not showing * Verify the **Phone Orders (MOTO)** setting is enabled in `WooCommerce > Settings > Payments > Stripe Terminal` * Make sure you're connected to a compatible reader (see [Supported Terminals](#supported-terminals-internet-connected)) — the toggle is hidden for other reader types * The toggle does not appear when using the simulator MOTO payment fails with an error * Confirm that Stripe has enabled MOTO permissions on your account — contact [Stripe support](https://support.stripe.com/contact) if you haven't already * Double-check that the card details were entered correctly on the reader * MOTO payments may have stricter fraud checks — ensure the card is valid and has sufficient funds SSL certificate errors * Stripe Terminal requires HTTPS - ensure your site has a valid SSL certificate * Check that your SSL certificate is properly configured ### Getting Help[​](#getting-help "Direct link to Getting Help") For technical support: * Visit the [GitHub repository](https://github.com/wcpos/stripe-terminal-for-woocommerce) to report issues * Check the [Stripe Terminal documentation](https://stripe.com/docs/terminal) for hardware-specific guidance * Contact Stripe support for account-related issues ## Screenshots[​](#screenshots "Direct link to Screenshots") Screenshots will be added in a future update to show: * Gateway configuration in WooCommerce payment settings * POS checkout interface with Stripe Terminal selection * Simulator testing interface with various payment methods --- # SumUp Terminal Gateway The SumUp Terminal gateway enables you to accept card payments using SumUp card readers directly within WCPOS. This gateway provides seamless integration with SumUp's payment processing system for in-person transactions. ## Features[​](#features "Direct link to Features") #### Hardware Integration Connect SumUp card readers to your POS system via internet connection #### Real-time Processing Instant payment processing and order completion #### Secure Transactions PCI-compliant payment processing through SumUp #### Easy Pairing Simple device pairing process with pairing codes ## Installation[​](#installation "Direct link to Installation") 1 #### Install SumUp Terminal for WooCommerce Install from `WP Admin > POS > Settings > Extensions`, or download the latest **plugin zip asset** (not the GitHub source-code zip or tarball) from the [GitHub releases page](https://github.com/wcpos/sumup-terminal-for-woocommerce/releases) and upload it via `Plugins > Add New > Upload Plugin`. 2 #### Configure SumUp Settings 1. Navigate to `WP Admin > WooCommerce > Settings > Payments` 2. Find **SumUp Terminal** in the payment methods list 3. Click on **SumUp Terminal** to access settings 4. Enter your **SumUp API Key** (available from your SumUp merchant dashboard) 5. Save the settings note You do not need to enable the SumUp Terminal gateway in WooCommerce settings. It will be enabled specifically for the POS in a later step. 3 #### Pair Your SumUp Terminal 1. On the same settings page, locate the **Pair Reader** section 2. On your SumUp device, navigate to the pairing screen to display the pairing code 3. Enter the pairing code displayed on your SumUp device 4. Click **"Pair Reader"** to establish the connection 5. Wait for confirmation that the reader has been successfully paired Important The reader must be successfully paired before you can process payments. Ensure the pairing process is completed before proceeding. 4 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **SumUp Terminal** gateway in the list 3. Enable the gateway for use in the POS 4. Save your settings ## Usage[​](#usage "Direct link to Usage") ### Processing Payments[​](#processing-payments "Direct link to Processing Payments") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "SumUp Terminal" as the payment method 3. **Start Payment**: Click to initiate a new payment on your SumUp device 4. **Customer Payment**: Customer completes payment on the SumUp terminal 5. **Automatic Completion**: The order automatically completes when payment is detected ### Payment Controls[​](#payment-controls "Direct link to Payment Controls") When using the SumUp Terminal gateway, you have the following options: * **Start New Payment**: Initiate a payment request on the connected terminal * **Cancel Payment**: Cancel a payment currently in process * **Payment Status**: Monitor the current status of the payment process ### Order Management[​](#order-management "Direct link to Order Management") * **Automatic Updates**: Orders are automatically marked as completed upon successful payment * **Payment Tracking**: All payment details are recorded in the order notes * **Receipt Generation**: Standard POS receipts are generated after successful payments ## Requirements[​](#requirements "Direct link to Requirements") SumUp Account : Active SumUp merchant account API Access : SumUp API key from your merchant dashboard Compatible Hardware : SumUp card reader device WCPOS : Pro version required for POS checkout Stable Connection : Reliable internet connection for API communication ## Hardware Compatibility[​](#hardware-compatibility "Direct link to Hardware Compatibility") Connectivity Requirements This implementation uses SumUp's JavaScript SDK, which means it works through web applications but requires **internet-connected terminals only**. Bluetooth terminals are not currently supported. ### Supported Terminals (Internet-Connected)[​](#supported-terminals-internet-connected "Direct link to Supported Terminals (Internet-Connected)") * **SumUp Solo** ✅ - WiFi/Ethernet connected terminal ### Unsupported Terminals (Bluetooth)[​](#unsupported-terminals-bluetooth "Direct link to Unsupported Terminals (Bluetooth)") * **SumUp Air** ❌ - Bluetooth only * **SumUp 3G** ❌ - Bluetooth only Future Support Bluetooth terminal support is planned for a future iOS and Android app release. When available, this will enable support for all SumUp certified terminals including the Air and 3G models. ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### Common Issues[​](#common-issues "Direct link to Common Issues") Reader won't pair * Ensure you're using a supported internet-connected terminal (Solo only) * Verify your SumUp Solo device is connected to WiFi and online * Check that the device is in pairing mode and pairing code is entered correctly * Confirm your SumUp account has API access enabled * Ensure stable internet connection during pairing Payment not processing * Verify the reader is properly paired * Check that your SumUp account is active and in good standing * Ensure the device has sufficient battery and connectivity * Confirm API key is correct and active Order not completing * Check internet connection stability * Verify webhook settings in your SumUp account * Ensure the payment was successful on the SumUp terminal * Check WordPress error logs for API communication issues ### API Rate Limits[​](#api-rate-limits "Direct link to API Rate Limits") The gateway is optimized to reduce API calls and avoid rate limiting: * Payment status is checked efficiently * Unnecessary API requests are minimized * Automatic retry logic handles temporary failures ### Getting Help[​](#getting-help "Direct link to Getting Help") For technical support: * Visit the [GitHub repository](https://github.com/wcpos/sumup-terminal-for-woocommerce) to report issues * Check the [SumUp developer documentation](https://developer.sumup.com/) for API-related questions * Contact SumUp support for account and hardware issues ## Screenshots[​](#screenshots "Direct link to Screenshots") Screenshots will be added in a future update to show: * SumUp API key configuration and device pairing interface * Gateway enablement in WCPOS settings * Payment processing workflow in the POS checkout --- # Vipps MobilePay Gateway The Vipps MobilePay gateway lets you accept phone-based payments directly within WCPOS. Customers pay by scanning a QR code on screen or confirming a push notification on their phone — no card reader hardware needed. ## Features[​](#features "Direct link to Features") #### QR Code Payments Display a QR code at checkout for customers to scan and pay with their phone #### Push Notifications Send a payment request straight to the customer's phone by entering their number #### Nordic Coverage Works with Vipps in Norway, MobilePay in Denmark and Finland #### Auto Capture Capture funds immediately after authorization, or reserve for manual capture ## Installation[​](#installation "Direct link to Installation") 1 #### Install WCPOS Vipps MobilePay Install from `WP Admin > POS > Settings > Extensions`, or download the latest **plugin zip asset** (not the GitHub source-code zip or tarball) from the [GitHub releases page](https://github.com/wcpos/wcpos-vipps/releases) and upload it via `Plugins > Add New > Upload Plugin`. 2 #### Configure Vipps Credentials 1. Navigate to `WP Admin > WooCommerce > Settings > Payments` 2. Find **WCPOS Vipps MobilePay** in the payment methods list 3. Click on **WCPOS Vipps MobilePay** to access settings 4. Enter your credentials from the [Vipps Portal](https://portal.vipps.no/): * **Merchant Serial Number (MSN)** * **Client ID** * **Client Secret** * **Subscription Key** 5. Save the settings note You don't need to enable the gateway here for POS use — it will be enabled specifically for the POS in the next step. Enabling it in WooCommerce settings would also make it available on your online store checkout, which can be useful for testing. Already using the Vipps plugin? If you have the official [Checkout with Vipps MobilePay](https://wordpress.org/plugins/woo-vipps/) plugin installed, your credentials will be imported automatically when you activate this plugin. You can skip the manual credential entry. 3 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **WCPOS Vipps MobilePay** gateway in the list 3. Enable the gateway for use in the POS 4. Save your settings ## Usage[​](#usage "Direct link to Usage") ### Processing Payments — QR Code[​](#processing-payments--qr-code "Direct link to Processing Payments — QR Code") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "Vipps MobilePay" as the payment method 3. **Generate QR Code**: Click the "Generate QR Code" button 4. **Customer Scans**: The customer scans the QR code with their Vipps or MobilePay app 5. **Customer Confirms**: The customer confirms payment in their app 6. **Automatic Completion**: The order completes automatically once payment is authorized ### Processing Payments — Send to Phone[​](#processing-payments--send-to-phone "Direct link to Processing Payments — Send to Phone") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "Vipps MobilePay" as the payment method 3. **Enter Phone Number**: Type the customer's phone number 4. **Send to Phone**: Click the "Send to Phone" button 5. **Customer Confirms**: The customer receives a push notification or is directed to the Vipps landing page, then confirms payment in their app 6. **Automatic Completion**: The order completes automatically once payment is authorized The plugin automatically detects the best method for sending the payment request to the customer's phone: * **Direct push** (preferred) — Sends a notification straight to the customer's Vipps app. This is the fastest experience but requires Vipps to enable `PUSH_MESSAGE` on your sales unit (see [Enabling Direct Push](#enabling-direct-push) below). * **Landing page fallback** — If direct push isn't enabled, the plugin opens the Vipps landing page in a new browser tab. The landing page handles sending the notification. This works immediately with no special approval. The first time the plugin detects that direct push isn't available, you'll see a brief message asking you to click "Send to Phone" again. After that, it remembers the result and works seamlessly. ### Enabling Direct Push[​](#enabling-direct-push "Direct link to Enabling Direct Push") The direct push flow provides the best experience for phone payments — no extra tabs, no landing pages. To enable it: 1. Log in to [portal.vippsmobilepay.com](https://portal.vippsmobilepay.com) 2. Contact your Vipps key account manager, partner manager, or customer service 3. Tell them: **"I need PUSH\_MESSAGE enabled on my MSN for use with a POS integration"** Once approved, the plugin detects the change automatically within 24 hours and switches to the direct push flow. You'll see a reminder notice on the gateway settings page while you're using the landing page fallback. ### Cancelling a Payment[​](#cancelling-a-payment "Direct link to Cancelling a Payment") While waiting for the customer to confirm, you can click the **Cancel Payment** button to abort the transaction. This cancels the pending payment on the Vipps side and resets the checkout interface. ### Refunds[​](#refunds "Direct link to Refunds") Refunds are handled through the standard WooCommerce refund process. Open the order, click **Refund**, enter the amount, and the refund is processed through the Vipps API automatically. ## Supported Markets[​](#supported-markets "Direct link to Supported Markets") Vipps MobilePay operates across the Nordic region under two brands: | Region | Brand | Currencies | | ---------------- | --------- | ---------- | | Norway | Vipps | NOK | | Denmark, Finland | MobilePay | DKK, EUR | Your merchant account determines which markets and currencies are available. Customers in any supported market can pay using their local Vipps or MobilePay app. ## Requirements[​](#requirements "Direct link to Requirements") Vipps Account : Active Vipps MobilePay merchant account with API credentials API Credentials : Merchant Serial Number, Client ID, Client Secret, and Subscription Key WCPOS : Pro version required for POS checkout. The gateway also works on the standard WooCommerce web checkout without Pro. HTTPS : Your site must use SSL/HTTPS (required by the Vipps API) ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### Common Issues[​](#common-issues "Direct link to Common Issues") Payment not completing * The checkout polls for up to 5 minutes — if the customer doesn't confirm within that window, the payment times out * Check that you're not mixing up test mode and production credentials * Verify your internet connection is stable on both the POS device and the customer's phone Invalid credentials error * Double-check all four credential fields (MSN, Client ID, Client Secret, Subscription Key) * Make sure you're using test credentials when test mode is enabled, and production credentials when it's disabled * Verify your credentials in the [Vipps Portal](https://portal.vipps.no/) 'Send to Phone' opens a new tab instead of sending directly This means your Vipps account doesn't have `PUSH_MESSAGE` enabled yet. The plugin is using the landing page fallback, which works but adds an extra step. To get the smoother direct push experience, contact Vipps and ask them to enable PUSH\_MESSAGE on your sales unit (MSN). See [Enabling Direct Push](#enabling-direct-push) above. QR code not generating * Confirm your site is running over HTTPS — the Vipps API rejects requests from HTTP sites * Check the WooCommerce logs (`WooCommerce > Status > Logs`) for API error details * Verify your merchant account is active and has the ePayment API enabled ### Getting Help[​](#getting-help "Direct link to Getting Help") For technical support: * Visit the [GitHub repository](https://github.com/wcpos/wcpos-vipps) to report issues * Check the [Vipps developer documentation](https://developer.vippsmobilepay.com/) for API-related questions * Contact Vipps MobilePay support for account and credential issues ## Screenshots[​](#screenshots "Direct link to Screenshots") Screenshots will be added in a future update to show: * Gateway configuration in WooCommerce payment settings * POS checkout interface with QR code and push notification options * Payment confirmation flow --- # Web Checkout Gateway The Web Checkout gateway allows customers to complete their POS transactions using your web store's checkout system. This gateway creates a seamless bridge between your in-store POS and online payment methods, perfect for situations where customers prefer to pay using their own devices or when you need access to web-only payment methods. ## Features[​](#features "Direct link to Features") #### Seamless Integration Direct link from POS to web checkout #### All Payment Methods Access to all your web store's enabled payment gateways #### Customer Control Customers can pay using their own devices and preferred methods #### Order Synchronisation Automatic order updates between POS and web store ## Installation[​](#installation "Direct link to Installation") 1 #### Download and Install 1. Visit the [Web Checkout Gateway releases page](https://github.com/wcpos/web-checkout-gateway/releases) 2. Download the latest **woocommerce-pos-web-checkout-gateway.zip** file 3. In your WordPress admin, go to `Plugins > Add New > Upload Plugin` 4. Upload the zip file and activate the plugin 2 #### Enable in WCPOS 1. Go to `WP Admin > POS > Settings > Checkout` 2. Find the **WCPOS Web Checkout Gateway** in the list 3. Enable the gateway for use in the POS 4. Save your settings note This gateway leverages your existing WooCommerce payment methods, so ensure you have at least one web payment gateway properly configured (Stripe, PayPal, etc.). ## Usage[​](#usage "Direct link to Usage") ### Initiating Web Checkout[​](#initiating-web-checkout "Direct link to Initiating Web Checkout") 1. **Add Items**: Add products to your cart in the POS 2. **Select Gateway**: Choose "Web Checkout" as the payment method 3. **Generate Link**: The system creates a unique checkout link for the order 4. **Customer Access**: Customer clicks the link to access the web checkout 5. **Online Payment**: Customer completes payment using web store payment methods ### Payment Process[​](#payment-process "Direct link to Payment Process") The Web Checkout gateway follows this workflow: 1. **Order Creation**: POS creates a pending order in WooCommerce 2. **Checkout Link**: System generates a secure, unique payment link 3. **Customer Redirect**: Customer is directed to the web checkout page 4. **Payment Selection**: Customer chooses from available web payment methods 5. **Payment Processing**: Standard WooCommerce checkout process handles payment 6. **Order Completion**: Order status updates automatically upon successful payment ### POS Workflow[​](#pos-workflow "Direct link to POS Workflow") After initiating web checkout: 1. **Monitor Status**: Keep the POS order screen open to monitor payment status 2. **Customer Payment**: Customer completes payment on their device or your tablet 3. **Automatic Update**: Order status updates in real-time when payment is received 4. **Process Payment**: Click "Process Payment" button in POS to continue to receipt 5. **Receipt Generation**: Generate and print receipt as normal ## Use Cases[​](#use-cases "Direct link to Use Cases") ### Perfect For[​](#perfect-for "Direct link to Perfect For") * **Customer Preference**: Customers who prefer to use their own payment apps or cards * **Complex Payments**: Transactions requiring payment methods not available in POS * **Split Payments**: Customers wanting to use multiple payment methods * **Loyalty Programs**: Access to web-based loyalty point redemption * **Gift Cards**: Customers with digital gift cards or store credit * **International Cards**: Payment methods that work better through web gateways ### Workflow Examples[​](#workflow-examples "Direct link to Workflow Examples") #### Retail Store 1. Customer shops in-store and brings items to checkout 2. Customer prefers to pay with their mobile wallet app 3. Staff selects Web Checkout gateway 4. Customer scans QR code or clicks link on their phone 5. Customer completes payment using preferred method 6. Staff processes receipt and completes transaction #### Service Business 1. Complete service and add charges to POS 2. Customer wants to pay with business credit card 3. Generate web checkout link 4. Customer enters payment details on secure web form 5. Payment processes through your web gateway 6. Order completes and receipt is generated ## Technical Details[​](#technical-details "Direct link to Technical Details") ### Order Management[​](#order-management "Direct link to Order Management") * **Pending Orders**: Orders are created with "pending payment" status * **Status Updates**: Automatic status changes when payment is received * **Order Notes**: Payment details are recorded in order notes * **Inventory**: Stock is reserved during the checkout process ### Security[​](#security "Direct link to Security") * **Unique Links**: Each checkout session has a unique, time-limited URL * **SSL Required**: All payment processing occurs over secure HTTPS connections * **PCI Compliance**: Leverages your existing PCI-compliant web payment gateways * **Session Management**: Secure session handling prevents unauthorized access ### Payment Methods[​](#payment-methods "Direct link to Payment Methods") The gateway provides access to all your configured WooCommerce payment methods: * **Credit/Debit Cards**: Stripe, Square, Authorize.net, etc. * **Digital Wallets**: PayPal, Apple Pay, Google Pay * **Bank Transfers**: Direct bank payment methods * **Buy Now, Pay Later**: Klarna, Afterpay, Sezzle * **Cryptocurrency**: Bitcoin and other crypto payment gateways * **Local Methods**: Region-specific payment methods ## Requirements[​](#requirements "Direct link to Requirements") WCPOS : Pro version required for POS checkout Web Payment Gateways : At least one online payment method configured in WooCommerce SSL Certificate : HTTPS required for secure payment processing Modern Browser : Customer device must support modern web standards ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") ### Common Issues[​](#common-issues "Direct link to Common Issues") Checkout link not working * Verify SSL certificate is properly installed * Check that WooCommerce permalinks are configured correctly * Ensure web payment gateways are active and configured * Test with a different browser or device Payment not processing * Confirm web payment gateways are properly configured * Check payment gateway logs for error messages * Verify customer's payment method is supported * Test the web checkout process independently Order not updating in POS * Check internet connection stability * Verify WordPress cron jobs are running properly * Refresh the POS order screen * Check order status in WooCommerce admin Customer can't access checkout * Ensure the checkout link hasn't expired * Verify customer's device has internet connectivity * Check that the order hasn't been cancelled or completed * Test the link on a different device ### Performance Optimisation[​](#performance-optimisation "Direct link to Performance Optimisation") For optimal performance: * **Caching**: Configure caching plugins to exclude checkout pages * **CDN**: Ensure CDN settings don't interfere with checkout process * **Database**: Optimise database for faster order processing * **Hosting**: Use reliable hosting with good uptime ### Getting Help[​](#getting-help "Direct link to Getting Help") For technical support: * Visit the [GitHub repository](https://github.com/wcpos/web-checkout-gateway) to report issues * Check WooCommerce payment gateway documentation * Test your web checkout process regularly * Monitor payment gateway logs for issues ## Screenshots[​](#screenshots "Direct link to Screenshots") Screenshots will be added in a future update to show: * Web Checkout gateway selection and link generation in POS * Customer payment process on the web store checkout * Order completion and receipt processing workflow --- # POS Screen Overview The POS screen is the main interface for selling products. It's where you'll spend most of your time when using WCPOS. ## Screen Layout[​](#screen-layout "Direct link to Screen Layout") ### Header[​](#header "Direct link to Header") The header bar displays: * **Store name** - The name of your connected WooCommerce store * **Connectivity indicator** - Green dot when connected to the server, yellow/red when offline * **User menu** - Click to access settings, switch users, or log out ### Navigation Drawer[​](#navigation-drawer "Direct link to Navigation Drawer") The left sidebar provides quick access to all main screens. The selling screen and the diagnostic/support screens are in the free plugin; the management screens (Products, Orders, Customers, Reports) are part of [WCPOS Pro](/getting-started/free-vs-pro.md). | Icon | Screen | Description | Edition | | ---- | ---------------- | ----------------------------------------------------------------------- | ------- | | | **POS** | Main selling interface (you are here) | Free | | | **Products** | Inventory management — edit stock, prices, and product details | Pro | | | **Orders** | Order history — look up, reprint, edit, and refund past orders | Pro | | | **Customers** | Customer management — add and edit customers | Pro | | | **Reports** | Sales reports — end-of-day totals by payment method, cashier, and store | Pro | | | **Store health** | Sync performance, database coverage, and activity logs | Free | | | **Support** | Discord support channel | Free | The version number is displayed at the bottom of the drawer. Free vs Pro screens On the free plugin you can still **select** an existing customer at the till — you just can't open the management screens. Products, Orders, Customers, and Reports unlock with Pro. For a full breakdown see [Free vs Pro](/getting-started/free-vs-pro.md). ## Responsive Layout[​](#responsive-layout "Direct link to Responsive Layout") WCPOS adapts to different screen sizes: ### Desktop / Tablet (Large Screens)[​](#desktop--tablet-large-screens "Direct link to Desktop / Tablet (Large Screens)") On larger screens, the POS displays a **two-column layout**: * **Left column:** Product Panel - search and browse products * **Right column:** Cart Panel - view and manage the current order The columns are **resizable** - drag the divider between them to adjust the proportions. ### Mobile (Small Screens)[​](#mobile-small-screens "Direct link to Mobile (Small Screens)") On smaller screens, the POS uses a **tab-based layout**: * **Products tab:** Browse and add products to cart * **Cart tab:** View cart, manage line items, and checkout Switch between tabs using the navigation bar at the bottom of the screen. ## Main Components[​](#main-components "Direct link to Main Components") ### Product Panel[​](#product-panel "Direct link to Product Panel") The left side of the POS is the [Product Panel](/pos/product-panel/.md), where you: * Search for products by name, SKU, or barcode * Filter products by stock status, category, tags, etc. * Add products to the cart [Learn more about the Product Panel →](/pos/product-panel/.md) ### Cart Panel[​](#cart-panel "Direct link to Cart Panel") The right side of the POS is the [Cart Panel](/pos/cart/.md), where you: * View items in the current order * Edit quantities and prices * Select or add customers * Access order actions (notes, void, checkout) [Learn more about the Cart Panel →](/pos/cart/.md) ### Checkout[​](#checkout "Direct link to Checkout") When you're ready to complete a sale, click **Checkout** to open the [Checkout modal](/pos/checkout/.md): * Apply coupon codes * Select payment method * Process payment * Print or email receipt [Learn more about Checkout →](/pos/checkout/.md) ## Keyboard Shortcuts[​](#keyboard-shortcuts "Direct link to Keyboard Shortcuts") WCPOS supports keyboard shortcuts for faster operation. Access the full list via the Settings modal or see [Keyboard Shortcuts](/settings/store/hotkeys.md). Common shortcuts: | Shortcut | Action | | ------------------ | -------------------- | | `Ctrl + F` | Focus search bar | | `Ctrl + Shift + S` | Open Settings | | `Escape` | Close modal/dialogue | ## Connectivity[​](#connectivity "Direct link to Connectivity") The green indicator in the header shows your connection status: * **Green** - Connected to the WooCommerce server * **Yellow** - Connection issues, retrying * **Red** - Offline mode While offline, you can browse cached products and customers and complete sales with offline-capable payment methods; those orders queue locally and sync automatically. Web and integrated gateways still need their respective services to be reachable. --- # Cart Panel The Cart Panel is the right side of the POS screen where you manage the current order. Here you can view items, edit quantities and prices, select customers, and proceed to checkout. ## Interface Overview[​](#interface-overview "Direct link to Interface Overview") ### Customer Selector[​](#customer-selector "Direct link to Customer Selector") At the top of the Cart Panel: * **Customer badge** - Shows the current customer (e.g., "Guest" or customer name) * **Add customer icon** () - Create a new customer * **Display settings** () - Configure cart columns and options Click the customer badge to search for and select a different customer. ### Line Items[​](#line-items "Direct link to Line Items") The main area displays items in the current order: * **QTY** - Quantity (editable) * **Name** - Product name with variation attributes * **Price** - Unit price (editable) * **Total** - Line total See [Line Items](/pos/cart/line-items.md) for details on editing. ### Add to Cart Options[​](#add-to-cart-options "Direct link to Add to Cart Options") Below the line items, you can add special items: * **Add Miscellaneous Product** - Add a custom item with manual price entry * **Add Fee** - Add a fee line (e.g., gift wrapping, service charge) * **Add Shipping** - Add a shipping line with manual cost entry Line Item Types WooCommerce uses three types of line items: `line_item` (products), `fee_line` (fees), and `shipping_line` (shipping). Currently, only manual entry is supported for shipping—the POS does not calculate shipping costs automatically. ### Order Summary[​](#order-summary "Direct link to Order Summary") * **Subtotal** - Total before taxes and fees * **Tax** - Calculated tax amount (if applicable) * **Total** - Final order total ### Order Actions[​](#order-actions "Direct link to Order Actions") At the bottom of the Cart Panel: * **Order Note** - Add a note visible to the customer * **Order Meta** - Add custom metadata or view JSON * **Save to Server** - Save the order to WooCommerce with status `pos-open` See [Order Actions](/pos/cart/order-actions.md) for details. ### Main Buttons[​](#main-buttons "Direct link to Main Buttons") * **Void** (red) - Cancel/delete the current order * **Checkout** (green) - Proceed to payment ### Open Orders[​](#open-orders "Direct link to Open Orders") At the very bottom, a carousel shows all open orders: * Each cart displays its total * Click a cart to switch to it * The current cart is highlighted See [Open Orders](/pos/cart/open-orders.md) for details. ## Display Settings[​](#display-settings "Direct link to Display Settings") Click the sliders icon () to customise the Cart Panel display. ![Cart Settings](/img/pos-cart-settings.png) Cart Panel Display Settings ### Automatically Show Receipt After Checkout[​](#automatically-show-receipt-after-checkout "Direct link to Automatically Show Receipt After Checkout") If enabled, the receipt screen displays automatically after completing a sale. ### Automatically Print Receipt After Checkout[​](#automatically-print-receipt-after-checkout "Direct link to Automatically Print Receipt After Checkout") If enabled, the receipt prints automatically when shown. This saves time by reducing manual print steps. ### Quick Discounts[​](#quick-discounts "Direct link to Quick Discounts") A comma-separated list of discount percentages that appear as quick shortcut buttons. For example, entering `5,10,15,20` adds four buttons to the number pad on each line item's **Price** field. Tapping one takes that percentage off the line's price. See [Cart Discounts](/pos/cart/discounts.md#quick-discounts). ### Columns[​](#columns "Direct link to Columns") Configure which columns appear in the cart: | Column | Description | | ----------------- | --------------------------- | | **Qty** | Quantity of each item | | **Name** | Product name | | **Price** | Per-unit price | | **Regular Price** | Non-discounted price | | **Subtotal** | Line subtotal (qty × price) | | **Total** | Line total | | **Actions** | Remove item button | Some columns offer extra display options: | Column | Option | | ------------ | ----------------------------- | | **Qty** | Split (allow splitting items) | | **Name** | SKU | | **Price** | On Sale indicator | | **Subtotal** | Tax amount | | **Total** | Tax amount, On Sale indicator | ### Restore Default Settings[​](#restore-default-settings "Direct link to Restore Default Settings") Click to reset all cart display settings to their original defaults. ## Adding Items to Cart[​](#adding-items-to-cart "Direct link to Adding Items to Cart") ### From Product Panel[​](#from-product-panel "Direct link to From Product Panel") Click a product in the [Product Panel](/pos/product-panel/.md) to add it to the cart. For variable products, select the variation first. ### Miscellaneous Products[​](#miscellaneous-products "Direct link to Miscellaneous Products") For items not in your catalogue: 1. Click **Add Miscellaneous Product** 2. Enter a name and price 3. The item is added to the cart ### Fees[​](#fees "Direct link to Fees") To add a fee (e.g., gift wrapping): 1. Click **Add Fee** 2. Enter a name and amount 3. The fee appears as a separate line item ### Shipping[​](#shipping "Direct link to Shipping") To add shipping: 1. Click **Add Shipping** 2. Enter the shipping method name and cost 3. Shipping is added to the order ## Editing Cart Items[​](#editing-cart-items "Direct link to Editing Cart Items") All line items are editable directly in the cart. See [Line Items](/pos/cart/line-items.md) for details on: * Editing quantities * Changing prices * Viewing and editing raw JSON data * Removing items ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [Line ItemsEditing cart line items](/pos/cart/line-items.md) [Open OrdersManaging multiple carts](/pos/cart/open-orders.md) [Order ActionsNotes, metadata, and saving](/pos/cart/order-actions.md) [CheckoutProcessing payment](/pos/checkout/.md) --- # Cart Discounts WCPOS provides several ways for a cashier to discount an order on the fly: quick percentage buttons, direct line-item price edits, and order-level discount fees. For pre-configured promotions with usage rules, see [Coupons](/coupons/.md) (Pro). Looking for the Discount total? A price lowered at the till is recorded as the item's sale price, not as a WooCommerce discount — the native **Discount** total is reserved for coupons. [Why price changes and coupons are tracked differently](#why-tracked-differently) explains the model; if your totals changed after updating to v1.9.0, see [What changed in v1.9.0](#what-changed-in-v190). ## Quick Discounts[​](#quick-discounts "Direct link to Quick Discounts") Quick discount buttons let you take a percentage off a line item with a single tap. To configure them, open the cart [Display Settings](/pos/cart/.md#display-settings) and enter a comma-separated list of percentages in the **Quick Discounts** field. For example, `5,10,15,20` creates four shortcut buttons. The buttons appear in the number pad that opens when you click a line item's **Price** field. Tapping one reduces that line's price by the percentage; press **Done** to confirm. Each line item is discounted separately, so to discount several items, repeat this on each line. There is no button that discounts the whole order at once — for that, use an [order-level discount](#order-level-discounts). ## Line-Item Discounts[​](#line-item-discounts "Direct link to Line-Item Discounts") You can change the price of any individual line item directly in the cart: 1. Click the **Price** field on the line item 2. Enter the new price 3. Press **Enter** to confirm This is useful for price matching, staff discounts, or one-off adjustments. The line item's total updates automatically based on quantity × new price. See [Line Items](/pos/cart/line-items.md) for more on editing cart items. Splitting Items If a customer wants different discounts on portions of the same product (e.g., 3 at full price and 2 discounted), enable the **Split** option in cart [Display Settings](/pos/cart/.md#display-settings) to break a line item into separate lines. ## Order-Level Discounts[​](#order-level-discounts "Direct link to Order-Level Discounts") To apply a flat discount to the entire order (rather than individual items), add a **negative fee**: 1. Click **Add Fee** below the cart items 2. Enter a name (e.g., "Staff discount") 3. Enter the discount amount as a negative number (e.g., `-5.00`) The fee appears as a separate line item and reduces the order total. You can edit the fee's tax status and tax class using the three-dot menu if needed. ### How tax is calculated on a discount fee[​](#discount-fee-tax "Direct link to How tax is calculated on a discount fee") WCPOS taxes a negative fee from **the fee's own tax settings**: set its tax status to **None** and no tax is applied to it; leave it **Taxable** and it is taxed at its own tax class. The amount you type is the amount taken off — enter `-10.00` and the customer pays 10 less. WooCommerce core does this differently. On its own, WooCommerce treats a negative fee as a whole-basket discount and spreads its tax across the tax classes of every other item in the order, ignoring the tax status you set on the fee. It also doesn't account for tax-inclusive pricing, so on a store where **Prices Entered With Tax** is *Yes*, a `-10.00` fee would take **12.00** off at a 20% rate. WCPOS overrides that so the till takes off exactly what the cashier entered. This treatment belongs to the order, not to the app you happen to be using — recalculating a POS order from **WP Admin → Orders** won't change it. Non-POS orders keep WooCommerce's standard behaviour. Known limitation on tax-inclusive stores If your prices include tax, a discount fee gives the customer the correct total but leaves the **tax recorded on the order unchanged** — so the tax figure is slightly higher than the reduced amount would strictly warrant. It errs in the tax authority's favour, never the other way. If the recorded tax matters for your bookkeeping, use a [coupon](/coupons/.md) for the discount instead: coupons reduce the taxable amount and recalculate tax on it correctly. We're moving order-level POS discounts onto coupons in a future release for exactly this reason. ## POS Discounts vs WooCommerce Coupons[​](#pos-discounts-vs-woocommerce-coupons "Direct link to POS Discounts vs WooCommerce Coupons") The discounts on this page are ad-hoc adjustments cashiers apply at the till; WooCommerce **coupons** are pre-configured promotions with rules and tracking. Here's how they compare at a glance: | | POS Discounts | WooCommerce Coupons (Pro) | | -------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | **How applied** | Quick discount, line price edit, or negative fee | Enter a coupon code in the cart | | **Where configured** | On the fly by the cashier | Pre-configured in **WP Admin → Marketing → Coupons** | | **Tracking** | Recorded as the line price, like a sale price (see [why](#why-tracked-differently)) | Tracked as a coupon discount in WooCommerce reports | | **Restrictions** | None — the cashier sets any price | Usage limits, product/category restrictions, minimum spend, expiry, email rules | | **Best for** | Ad-hoc adjustments, price matching | Structured promotions, trackable discounts | Which should I use? For one-off price adjustments, the discounts on this page are simpler. If you need to track discount usage in WooCommerce reports or enforce rules like usage limits, use [Coupons](/coupons/.md). ## Why price changes and coupons are tracked differently[​](#why-tracked-differently "Direct link to Why price changes and coupons are tracked differently") WooCommerce has exactly one built-in concept of a discount: the **coupon**. A coupon belongs to the order — it's recorded in its own field, counted in the **Discount** column of reports, and carries its own rules such as usage limits and expiry dates. A **sale price** is not a discount to WooCommerce. It's simply the product's price right now: when an on-sale item is sold, the order records the price paid and nothing else. The regular price never appears on the order, and reports count the sale as ordinary revenue — WooCommerce itself keeps no record that the customer saved anything. Quick discounts and line-item price edits follow the sale-price model: the item is sold "on sale" at the price the cashier sets. That one rule explains the rest of this page — the WooCommerce **Discount** total stays at zero, coupons calculate against the lowered price, and "exclude sale items" coupons skip till-lowered items. (An order-level negative fee is different again: it's recorded as a fee line, not a price change.) Receipts are the one place customers expect to see what they saved, so WCPOS records the regular price alongside the new price on each line. That lets a receipt show sale savings and coupon discounts as separate figures without counting either twice — and without changing WooCommerce's order totals or reports. ## How POS Price Changes Interact with Coupons[​](#how-pos-price-changes-interact-with-coupons "Direct link to How POS Price Changes Interact with Coupons") When a cashier sets a custom price on a line item (e.g., reducing $18 to $16), and a coupon is then applied, the coupon calculates against the **POS-discounted price** ($16), not the original ($18). This prevents customers being over-discounted by stacking a cashier discount and a coupon against the original price. * POS-discounted items are treated as "on sale" by WooCommerce. If a coupon has **Exclude sale items** enabled, it will skip POS-discounted items — the same way it skips regular sale items. Developers can override this with the `woocommerce_pos_item_is_on_sale` filter. * Removing a coupon leaves the line at its POS-discounted price. Developer Reference For technical details on how POS price overrides are stored and the available filters, see the [POS Discount Reference](/reference/pos-discounts.md). ## What changed in v1.9.0[​](#what-changed-in-v190 "Direct link to What changed in v1.9.0") If you upgraded from v1.8 and the **Discount** total on receipts and reports now shows **0**, this is why: earlier versions recorded a till price change as a WooCommerce discount, which broke coupon math — a coupon applied on top calculated against the original price, over-discounting the order and undercharging the customer. From v1.9.0, the price set at the till **is** the line price, exactly as WooCommerce records a product on sale, and only coupons count as discounts. See [Why price changes and coupons are tracked differently](#why-tracked-differently) above. ### What this means for you[​](#what-this-means-for-you "Direct link to What this means for you") * **Receipts** can show the recorded regular price, regular-to-selling-price savings, and a combined **Total saved** value for those savings plus coupons. Price savings remain separate from the WooCommerce **Discount** field. * **Reports** show `discount_total = 0` when only POS line-item price changes were used. Only coupon discounts are counted. * **Coupons** now calculate correctly when stacked on POS-discounted items. * **The recorded regular and selling prices are stored** in POS line-item metadata (`_woocommerce_pos_data`), so the receipt can derive the saving without changing WooCommerce's discount totals. ### Showing the original price and savings on receipts[​](#showing-the-original-price-and-saving-on-receipts "Direct link to Showing the original price and savings on receipts") The current bundled price-bearing templates show the recorded regular price and saving when a product is on sale or its price is changed at the till. They also show **Total saved** when WCPOS can calculate a complete order-level figure. This total combines regular-price savings with coupon discounts without counting either one twice. Templates copied from the gallery are editable snapshots and are not overwritten by WCPOS updates. If you created your receipt before this change, either: 1. click **Use Template** on a fresh copy of the bundled template; or 2. update your existing template with the fields in the [Receipt Data Reference](/receipts/receipt-data.md#displaying-regular-price-and-savings). The main receipt fields are: | Field | Meaning | | ------------------------------------ | ---------------------------------------------------------------------------------- | | `lines[].regular_price_display` | Recorded regular unit price | | `lines[].selling_price_display` | Selling unit price before coupons | | `lines[].unit_savings_display` | Saving per item | | `lines[].line_regular_total_display` | Regular-price total for the line | | `lines[].line_savings_display` | Total saving for the line | | `totals.sale_savings_total_display` | Total regular-to-selling-price savings from catalogue sales and till price changes | | `totals.discount_total_display` | WooCommerce discount total; normally coupons on current orders | | `totals.total_saved_display` | Combined regular-price savings and WooCommerce discounts | | `totals.total_saved_complete` | Whether the combined total is complete and safe to display | Custom templates should guard the **Total saved** row so it disappears when historical price data is incomplete or nothing was saved — see the [Receipt Data Reference](/receipts/receipt-data.md#totals) for the exact pattern. WooCommerce reports are unchanged: native discount totals still contain coupons rather than current sale-price or till-price savings. Use `totals.total_saved` for receipts and continue to use [Coupons](/coupons/.md) when savings must also be tracked as WooCommerce discounts in reports. ## Known Limitations[​](#known-limitations "Direct link to Known Limitations") * **No automatic discount rules** — the POS doesn't support "buy 2, get 1 free" style automatic discounts. Use WooCommerce coupons for structured promotions. * **Quick discounts are percentage-only** — there's no built-in quick button for fixed-amount discounts. Use a negative fee or edit individual prices instead. * **Discount fees and tax-inclusive pricing** — an order-level discount fee charges the right total but doesn't reduce the tax recorded on the order. See [How tax is calculated on a discount fee](#discount-fee-tax). --- # Cart Line Items Every item in the cart is a line item that can be edited directly. WCPOS provides flexible inline editing for quantities, prices, and other details. ## Line Item Types[​](#line-item-types "Direct link to Line Item Types") WooCommerce uses three types of line items: | Type | Description | Examples | | ------------------ | ---------------------------- | ----------------------------------- | | **line\_item** | Products from your catalogue | T-shirt, Coffee mug | | **fee\_line** | Additional fees | Gift wrapping, Service charge | | **shipping\_line** | Shipping costs | Standard shipping, Express delivery | note Shipping costs are entered manually. The POS does not calculate shipping rates automatically. ## Editing Line Items[​](#editing-line-items "Direct link to Editing Line Items") ### Quantity[​](#quantity "Direct link to Quantity") Click the quantity field to edit it directly. Type a new number or use the spinner controls. ### Product Name[​](#product-name "Direct link to Product Name") For miscellaneous products and fees, you can edit the name directly by clicking on it. ### Price[​](#price "Direct link to Price") Click the price field to change the unit price. This is useful for: * Applying manual discounts * Price matching * Correcting pricing errors The total updates automatically based on quantity × price. A price edit is not a WooCommerce "discount" A lowered price is recorded as the item's sale price — receipts can show the saving, but the order's **Discount** total is reserved for coupons, and reports count the sale at the price paid. See [Cart Discounts](/pos/cart/discounts.md#why-tracked-differently) for why WooCommerce treats the two differently. ### Three-Dot Menu[​](#three-dot-menu "Direct link to Three-Dot Menu") Click the **⋮** (three dots) on any line item to access additional options: #### Edit Form[​](#edit-form "Direct link to Edit Form") Opens a detailed edit form for the line item, allowing you to modify all fields. #### Raw JSON View[​](#raw-json-view "Direct link to Raw JSON View") Displays the raw JSON data for the line item. This is extremely helpful for: * **Debugging** - See exactly what data is being sent to WooCommerce * **Troubleshooting** - Identify issues with custom fields or meta data * **Development** - Understand the data structure for integrations ### Remove Item[​](#remove-item "Direct link to Remove Item") Click the red **×** button to remove an item from the cart. ## Variation Attributes[​](#variation-attributes "Direct link to Variation Attributes") For variable products, the selected variation attributes display below the product name: ``` Hoodie Colour: Green Size: Large ``` These attributes are part of the line item data and are included in the order. ## Meta Data[​](#meta-data "Direct link to Meta Data") If you've configured [Meta Data Keys](/pos/product-panel/.md#meta-data-keys) in the Product Panel settings, that data is automatically copied to the line item when the product is added to the cart. You can view this meta data in the Raw JSON view. ## Splitting Line Items[​](#splitting-line-items "Direct link to Splitting Line Items") If enabled in [Display Settings](/pos/cart/.md#display-settings), you can split a line item into multiple lines. This is useful when a customer wants to apply different discounts to portions of the same product. ## Tips[​](#tips "Direct link to Tips") ### Quick Price Adjustments[​](#quick-price-adjustments "Direct link to Quick Price Adjustments") To quickly give a discount: 1. Click the price field 2. Enter the new price 3. Press Enter ### Keyboard Navigation[​](#keyboard-navigation "Direct link to Keyboard Navigation") * **Tab** - Move between editable fields * **Enter** - Confirm edit * **Escape** - Cancel edit ### Batch Edits[​](#batch-edits "Direct link to Batch Edits") For complex orders, consider using the three-dot menu to access the full edit form, which shows all fields at once. --- # Open Orders WCPOS allows you to work with multiple orders simultaneously. This is useful for handling customer holds, switching between transactions, and recovering from interruptions. ## Open Orders Carousel[​](#open-orders-carousel "Direct link to Open Orders Carousel") At the bottom of the Cart Panel, a horizontal carousel displays all open orders: * Each cart shows its **total amount** * The **current order** is highlighted * Click any cart to switch to it * Scroll left/right to see more carts ## Creating a New Order[​](#creating-a-new-order "Direct link to Creating a New Order") A new empty cart is always available. Simply click on an empty cart in the carousel or start adding products when the current cart is empty. ## Switching Between Orders[​](#switching-between-orders "Direct link to Switching Between Orders") Click on any order in the carousel to switch to it. The Cart Panel updates to show the selected order's contents. **Use cases:** * Customer steps away to get another item * Need to help a quick customer while a large order is in progress * Comparing prices or items between orders ## Saving Orders to Server[​](#saving-orders-to-server "Direct link to Saving Orders to Server") Orders exist in two states: ### Local Only[​](#local-only "Direct link to Local Only") By default, new orders are stored only in the local browser/app database. They will persist across page refreshes but: * Are not visible in WooCommerce admin * Will be lost if the local database is cleared * Are not accessible from other devices ### Saved to Server[​](#saved-to-server "Direct link to Saved to Server") Click **Save to Server** to create a WooCommerce order with the status `pos-open`. This: * Creates a real order in WooCommerce * Persists even if the local database is cleared * Can be accessed from other devices * Appears in WP Admin > WooCommerce > Orders When to Save Save orders to the server when: * A customer wants to hold an order for later pickup * You're ending your shift and another cashier will continue * You want a backup in case of app/browser issues ## Recovering Saved Orders[​](#recovering-saved-orders "Direct link to Recovering Saved Orders") If you've saved orders to the server, they can be accessed again by: 1. Opening the **Orders** screen (Pro feature) 2. Filtering by status `pos-open` 3. Reopening the order ## Order Persistence[​](#order-persistence "Direct link to Order Persistence") ### Local Storage[​](#local-storage "Direct link to Local Storage") WCPOS stores orders in the local database on the device. This provides: * Persistence across browser sessions * Fast access without network requests * Offline capability ### Sync with Server[​](#sync-with-server "Direct link to Sync with Server") When you save to server or checkout: * The order is sent to WooCommerce * A confirmation is received * Local and server data are synchronized ## Voiding Orders[​](#voiding-orders "Direct link to Voiding Orders") To remove an open order: 1. Switch to the order you want to remove 2. Click the **Void** button **What happens:** * **Unsaved orders:** Permanently deleted from the local database * **Saved orders:** Moved to Trash in WooCommerce and deleted locally To recover a voided saved order: 1. Go to `WP Admin > WooCommerce > Orders > Trash` 2. Restore the order ## Tips[​](#tips "Direct link to Tips") ### Keep Orders Organized[​](#keep-orders-organized "Direct link to Keep Orders Organized") With multiple open orders, it helps to: * Add customer names to orders for easy identification * Add order notes describing the hold reason * Save important orders to the server ### Shift Handoffs[​](#shift-handoffs "Direct link to Shift Handoffs") When ending a shift with open orders: 1. Save all important orders to the server 2. Add order notes explaining the status 3. The next cashier can access them from the Orders screen ### Offline Considerations[​](#offline-considerations "Direct link to Offline Considerations") If you lose connectivity: * Local orders remain accessible and you can continue adding items * You can complete an order with an offline-capable payment method; server-dependent gateways remain unavailable until their services are reachable * You cannot save orders to the server until reconnected * You cannot create new customers until reconnected --- # Order Actions The Order Actions panel is located at the bottom of the cart in the POS interface. It provides quick access to several essential order management features. ![Order Actions in the POS](/img/order-actions.png) Order Actions in the POS ## Order Note[​](#order-note "Direct link to Order Note") ![Order Note in the POS](/img/order-note.png) Order Note modal in the POS (left) and Order Note in the WP Admin (right) * Opens a dialogue to add a customer note to the order. * Customer notes are visible to the customer and appear on the receipt by default, in the customer's My Account area, and in the `WP Admin > WooCommerce > Orders > Order` under the shipping address. note Order notes are visible to customers. ## Order Meta[​](#order-meta "Direct link to Order Meta") ![Order Meta and JSON View in the POS](/img/order-meta.png) Order Meta and JSON View in the POS * Opens a modal to manage additional metadata for the order. * Features include: * Changing the order currency. * Adding a transaction ID (e.g., from an external payment terminal). * Adding custom meta data for the order. note Additional features will be added to this modal over time, including integration with other WooCommerce plugins. ### What is Meta Data in WooCommerce?[​](#what-is-meta-data-in-woocommerce "Direct link to What is Meta Data in WooCommerce?") Meta data provides extra information about orders and is accessible via the WooCommerce REST API. Developers and plugins use this data to extend functionality, such as integrating third-party services. ### JSON View[​](#json-view "Direct link to JSON View") * View the raw JSON representation of the order, useful for debugging or integration purposes. ## Save to Server[​](#save-to-server "Direct link to Save to Server") * Allows you to save open carts to the server, so they are securely stored and accessible for future use. * Creates a WooCommerce order with status `pos-open`. ### Why save?[​](#why-save "Direct link to Why save?") When a new order is created in the POS, it only exists locally. Saving the order ensures it persists, even if the local database is cleared. See [Open Orders](/pos/cart/open-orders.md) for more details on managing saved orders. ## Void[​](#void "Direct link to Void") * Two Scenarios: * Unsaved Orders: * If the order has not been saved to the server, it will be permanently deleted from the local database. * Saved Orders: * If the order is saved to the server, it will be moved to the Trash folder in WooCommerce and deleted from the local database. * To recover a voided order: * Go to `WP Admin > WooCommerce > Orders > Trash`. ## Checkout[​](#checkout "Direct link to Checkout") * Saves the order to the server and initiates the checkout process. * Opens the [checkout screen](/pos/checkout/.md) to complete the payment. --- # Checkout When you're ready to complete a sale, click the **Checkout** button to open the checkout modal. This is where you process payment and complete the order. ## Checkout Modal Overview[​](#checkout-modal-overview "Direct link to Checkout Modal Overview") The checkout modal displays: * **Order number** - The WooCommerce order ID * **Amount to Pay** - Total amount due * **Checkout Settings** button - Troubleshoot display issues * **Cashier** - Who is processing the order * **Customer** - The customer for this order (clickable link) * **Add Coupon** button - Apply discount codes * **Order summary** - Products, quantities, and totals * **Payment methods** - Available payment options * **Cancel / Process Payment** buttons ## Payment Methods[​](#payment-methods "Direct link to Payment Methods") ### Available in Free Version[​](#available-in-free-version "Direct link to Available in Free Version") The free version of WCPOS includes two payment gateways: * **Cash** - With amount tendered and change calculator * **Card** - For external card terminals ### Additional Gateways (Pro)[​](#additional-gateways-pro "Direct link to Additional Gateways (Pro)") Pro Feature Additional payment gateways require [WCPOS Pro](/getting-started/pro-license.md). With Pro, you can enable: * **Stripe Terminal** - Direct integration with Stripe card readers * **SumUp Terminal** - Integration with SumUp card readers * **Custom Gateways** - Create your own payment integrations See [Payment](/payment/.md) for details on configuring gateways. ### Selecting a Payment Method[​](#selecting-a-payment-method "Direct link to Selecting a Payment Method") Click on a payment method to select it. The form updates to show relevant fields: **Cash:** * **Amount Tendered** - Enter the amount the customer gives you * **Change** - Automatically calculated change to return **Card:** * Process payment on your external card terminal * Click Process Payment to complete ## Coupons[​](#coupons "Direct link to Coupons") The cart includes an **Add Coupon** input above the totals (Pro only). Type the code or search by description; the coupon validates locally and appears as a removable pill. Multiple coupons stack sequentially. See **[Applying Coupons at the Till](/coupons/applying-coupons.md)** for the full workflow — search, pills, sequential discounts, and the table of validation errors and resolutions. For coupon types, validation rules, and setup in WooCommerce, see [Coupons](/coupons/.md). ## Processing Payment[​](#processing-payment "Direct link to Processing Payment") 1. Select a payment method 2. For cash, enter the amount tendered — WCPOS shows the **change due** in the order's own currency 3. Click **Process Payment** 4. The order is completed and the [receipt](/receipts/at-checkout.md) is shown Amounts follow the order's currency Cash **change** and card **cashback** are shown in the currency of the order being sold, not your site's default currency — so a sale rung up in a store that trades in a different currency displays the right symbol and amount. One payment method per order An order is paid with a single payment method — WCPOS doesn't currently support split or partial payments (e.g. part cash, part card) across one order. Split-payment support is on the [roadmap](https://github.com/orgs/wcpos/projects/4). ## Checkout Settings (Troubleshooting)[​](#checkout-settings-troubleshooting "Direct link to Checkout Settings (Troubleshooting)") The checkout modal uses an iframe/webview to display the WooCommerce Order Pay page. This leverages WooCommerce's existing payment infrastructure, meaning any payment gateway that works with WooCommerce should work in the POS. However, theme and plugin scripts can sometimes interfere. Click **Checkout Settings** to troubleshoot: ![Checkout Settings in the Checkout Modal](/img/checkout-settings.png) Checkout Settings in the Checkout Modal ![Form to disable all styles and scripts](/img/disable-styles-and-scripts.png) Form to disable all styles and scripts ### Disable All Styles and Scripts[​](#disable-all-styles-and-scripts "Direct link to Disable All Styles and Scripts") Nuclear Option This is the nuclear option and should only be used for testing or in rare cases where the developer knows what they are doing. Disabling all wp\_head scripts will remove even the WooCommerce scripts necessary to expand/contract the payment gateways, potentially breaking payment functionality. * **Disable wp\_head** - Removes all scripts/styles from the WordPress header * **Disable wp\_footer** - Removes all scripts/styles from the WordPress footer ### Disable Selected Styles[​](#disable-selected-styles "Direct link to Disable Selected Styles") Selectively disable CSS that may cause display issues: * wp-emoji-styles * wp-block-library * classic-theme-styles * woocommerce-layout * woocommerce-smallscreen * woocommerce-general * etc. ### Disable Selected Scripts[​](#disable-selected-scripts "Direct link to Disable Selected Scripts") Selectively disable JavaScript that may interfere with payment gateways: * wc-add-to-cart * selectWoo * wc-checkout * woocommerce * html5shiv * etc. tip If a payment gateway doesn't display correctly: 1. Try disabling theme styles first 2. Then try disabling WooCommerce scripts that aren't needed 3. Be careful not to disable scripts required by your payment gateway ## Cancel[​](#cancel "Direct link to Cancel") Click **Cancel** to close the checkout modal without completing the order. The order remains as an open cart. ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [ReceiptsAfter checkout, print or email receipts](/receipts/at-checkout.md) [Payment MethodsConfigure payment gateways](/payment/.md) [Custom GatewaysCreate custom payment integrations](/payment/gateways/.md) --- # Product Panel The Product Panel is the left side of the POS screen where you search, browse, and select products to add to the cart. ## Interface Overview[​](#interface-overview "Direct link to Interface Overview") ### Search Bar[​](#search-bar "Direct link to Search Bar") At the top of the panel, the search bar lets you quickly find products by: * **Product name** - Type any part of the product name * **SKU** - Search by Stock Keeping Unit * **Barcode** - Scan or type a barcode number See [Search & Filtering](/pos/product-panel/search-filtering.md) for detailed information. ### Display Settings[​](#display-settings "Direct link to Display Settings") Click the **sliders icon** () next to the search bar to open Display Settings. This allows you to customise which columns and information are shown in the product list. ### Filter Buttons[​](#filter-buttons "Direct link to Filter Buttons") Below the search bar, filter buttons let you narrow down products: * **In Stock** - Show only products with available inventory * **Featured** - Show products marked as featured in WooCommerce * **On Sale** - Show products currently on sale * **Category** - Filter by product category * **Tag** - Filter by product tag * **Brand** - Filter by brand (if using a brand plugin) Active filters appear highlighted. Click a filter again to remove it. ### Product List[​](#product-list "Direct link to Product List") The main area displays your products in a scrollable list. Each row shows: * **Product image** - Thumbnail of the product * **Product name** - With optional details (stock, SKU, categories, etc.) * **Price** - Current selling price (with sale prices shown when applicable) * **Action button** - Add to cart () or select variation () ### Product Types[​](#product-types "Direct link to Product Types") * **Simple products** show a green button to add directly to cart * **Variable products** show a green arrow to open the variation selector See [Variable Products](/pos/product-panel/variations.md) for more details. ### Footer[​](#footer "Direct link to Footer") At the bottom of the Product Panel: * **Tax status** - Shows the current tax calculation basis (e.g., "Tax based on: Shop base address"). Click to view active tax rates. * **Product count** - Shows how many products are displayed (e.g., "Showing 10 of 17") * **Sync button** () - Refresh products from the server. **Long press** for additional options: * **Sync** - Standard refresh from server * **Clear and Refresh** - Clear local data and reload everything ## Display Settings[​](#display-settings-1 "Direct link to Display Settings") Click the sliders icon () to customise the Product Panel display. ![POS Products Settings](/img/pos-products-settings.png) Product Panel Display Settings ### Show Out-of-Stock Products[​](#show-out-of-stock-products "Direct link to Show Out-of-Stock Products") Controls whether products that are currently out of stock are displayed. * **Enabled**: Out-of-stock products remain visible but can't be added to cart * **Disabled**: Out-of-stock products are hidden from the list ### Columns[​](#columns "Direct link to Columns") Configure which columns appear in the product list: | Column | Description | | ---------------------- | ------------------------------------- | | **Image** | Product thumbnail | | **Product** | Product name and details | | **SKU** | Stock Keeping Unit (separate column) | | **Barcode** | Product barcode (separate column) | | **Type** | Product type (simple, variable, etc.) | | **Stock** | Current stock quantity | | **Cost of Goods Sold** | Product cost price | | **Price** | Selling price | | **Actions** | Add to cart button | Two columns have extra display options you can toggle on: | Column | Display options | | ----------- | -------------------------------------------------------------------- | | **Product** | Stock, SKU, Barcode, Categories, Tags, Brands, Attributes, Meta Data | | **Price** | Tax info, On Sale indicator | ### Meta Data Keys[​](#meta-data-keys "Direct link to Meta Data Keys") A meta data key is a custom field stored on a product in WooCommerce. By default these stay on the product — they aren't copied onto the order. This setting lets you carry specific keys over to the cart line item when the product is added. **Example:** a bottle-deposit plugin stores a `_bottle_deposit` value on each product. Add that key here, and whenever the product is added to the cart its deposit value travels with the line item onto the order — so it shows up on the order, the receipt, and any downstream reports. Enter a comma-separated list of meta keys: ``` _bottle_deposit,_custom_field,_tracking_code ``` tip Meta keys are case-sensitive and must match exactly as stored in the product's meta data. When would I use this? Common cases for transferring product meta data to order line items: * **Bottle deposit plugins** — carry the deposit amount onto the order. * **Custom product fields** — pass your own product data through to the order. * **Third-party integration data** — hand values off to other plugins that read order line items. * **Compliance / tracking information** — keep batch, lot, or tracking codes attached to what was sold. ### Restore Default Settings[​](#restore-default-settings "Direct link to Restore Default Settings") Click to reset all display settings to their original defaults. ## Adding Products to Cart[​](#adding-products-to-cart "Direct link to Adding Products to Cart") ### Simple Products[​](#simple-products "Direct link to Simple Products") Click the green button to add a simple product to the cart. Each click adds one more unit. ### Variable Products[​](#variable-products "Direct link to Variable Products") Variable products (e.g., a t-shirt with size and colour options) show a green arrow. Click to: 1. **Quick popover** - Select variation from a dropdown 2. **Expand inline** - Click "Expand" to see all variations in the list See [Variable Products](/pos/product-panel/variations.md) for more details. ### Barcode Scanning[​](#barcode-scanning "Direct link to Barcode Scanning") Connect a USB or Bluetooth barcode scanner to quickly add products. When you scan a barcode, WCPOS automatically searches for and adds the matching product. See [Barcode Scanning](/pos/product-panel/barcode-scanning.md) for setup instructions. ## Why Can't I See Some Products?[​](#why-cant-i-see-some-products "Direct link to Why Can't I See Some Products?") If products are missing from your Product Panel, check: * **POS visibility** - Products set to "Online Only" won't appear in the POS. See [POS Only Products](/products/pos-only-products.md). * **Stock settings** - If "Show Out-of-Stock Products" is disabled in Display Settings, out-of-stock items are hidden. * **Sync status** - New or recently updated products may need a sync. Long press the sync button and select **"Clear and Refresh"**. * **Filters** - Check if you have active filters (Category, Tag, etc.) that might be hiding products. ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [Search & FilteringDetailed search functionality](/pos/product-panel/search-filtering.md) [Barcode ScanningScanner setup and configuration](/pos/product-panel/barcode-scanning.md) [Variable ProductsWorking with product variations](/pos/product-panel/variations.md) --- # Barcode Scanning Most barcode scanners behave like a keyboard connected to your device. When you scan a barcode, the WCPOS detects that the characters were entered faster than normal typing. It uses these "fast key presses" to identify the input as a barcode scan. This works out of the box with almost every scanner — but scanners also support other [connection modes](#connection-modes) that WCPOS can connect to directly. ## Configuring Barcode Scanning[​](#configuring-barcode-scanning "Direct link to Configuring Barcode Scanning") Since a barcode scan happens very fast, the POS can tell the difference between a barcode and something typed in by hand. In the POS settings, you'll find options for fine-tuning how barcode detection works. ![Barcode Scanning Settings in the POS Settings](/img/barcode-scanning-settings.png) Barcode Scanning Settings in the POS Settings | Setting | Purpose | Typical value | | ------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | **Average input time** | How fast the input must be to count as a barcode | A short interval — fast enough that hand-typing won't trigger it | | **Minimum length** | How long the continuous string of characters must be to be treated as a barcode | Match the shortest barcode you use (e.g. 8 for EAN-8) | | **Prefix/Suffix removal** | Strips extra characters your scanner adds (a prefix or suffix) so only the main barcode remains | Leave empty unless your scanner is configured to add them | ## Connection Modes[​](#connection-modes "Direct link to Connection Modes") For a guided path through setup or troubleshooting, use the [Scanner Setup Wizard](/hardware/scanners/setup-wizard.md). Every barcode scanner ships in one of a few modes, and the mode decides how WCPOS can receive its scans: | Mode | How it arrives | Setup | | ---------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------- | | **Keyboard (HID)** — the factory default on almost every scanner | The scanner "types" the barcode; WCPOS recognises the fast keystrokes | None — pair or plug in and scan | | **Serial (SPP / USB-COM)** | A direct connection over USB serial or Bluetooth SPP | Switch the scanner's mode, then connect it in the Barcode settings | | **HID-POS** | A direct connection for USB scanners (via WebHID) | Switch the scanner's mode, then connect it in the Barcode settings | | **Bluetooth LE (vendor GATT)** | A direct Bluetooth Low Energy connection | Pair the scanner, then add it in the Barcode settings by its service UUID | Keyboard mode needs no setup and is right for most stores. A direct connection is worth it if scans sometimes arrive garbled (uppercase/symbol mix-ups from keyboard-layout differences) or land in the wrong place when the search box isn't focused — a directly connected scanner delivers every scan straight to WCPOS, regardless of typing speed, keyboard layout, or focus. A scanner in keyboard mode can't be connected directly Your device treats a keyboard-mode scanner exactly like a keyboard, and no app is allowed to take over a keyboard. If you press **Connect serial scanner** or **Connect HID scanner** in the Barcode settings and your scanner doesn't appear in the list, it is almost certainly still in keyboard mode. **To switch modes**, find the setup barcode in your scanner's manual (look for *"SPP mode"*, *"serial mode"*, or *"HID-POS mode"*) and scan it — the scanner reconfigures itself. For Bluetooth scanners, forget the old pairing in your device's Bluetooth settings and pair again after switching. Scanning the manual's *"HID"* or *"keyboard"* barcode switches it back at any time. Direct connections are supported in the Desktop app and Chrome-based browsers (using the browser's Web Serial and WebHID support). The Desktop app shows a device chooser inside the app; Chrome shows its own device picker. On iOS and Android, keyboard mode and camera scanning are the supported options, and Android additionally intercepts hardware-scanner key input directly. ## Camera scanning[​](#camera-scanning "Direct link to Camera scanning") Every platform — web, desktop, iOS, and Android — can scan with the device camera, so you don't need a dedicated scanner to get started. Open the camera from the scan icon in the search bar; it appears as a **resizable panel directly below the filters**, so the product list stays in view while you scan. Point the camera at a barcode and WCPOS reads it exactly as it would a hardware scan. ## What Happens When a Barcode is Detected?[​](#what-happens-when-a-barcode-is-detected "Direct link to What Happens When a Barcode is Detected?") When the POS detects a barcode, it looks in its local database to find a matching product or product variation. There are three possible outcomes: When a scan finds no local match, WCPOS falls back to your store online, downloads the matching product, and **adds it to the cart automatically** — so an unknown barcode still completes the sale, and the same scan is instant next time. Multiple matches usually means a data issue If more than one product shares the same barcode, the POS can't know which to add, so it drops the code into the search bar for you to choose. When this happens it's usually a sign your product data needs tidying up — each product should have a **unique** barcode. ## Scan feedback and behaviour[​](#scan-feedback-and-behaviour "Direct link to Scan feedback and behaviour") * **Scan sounds** — WCPOS can play a sound on each scan so cashiers get instant confirmation without looking at the screen. Sounds are optional and offer a choice of themes; turn them on and pick a theme in the [Barcode settings](/settings/store/barcode.md). * **On the Orders screen** — scans are routed to the Orders search field, so you can scan a barcode to find the order or product you're looking for. * **UPC-A barcodes** — a UPC-A scan resolves to the digits printed on the package, so the value the POS matches is the one your product data uses. ## Understanding Product Synchronisation[​](#understanding-product-synchronisation "Direct link to Understanding Product Synchronisation") The POS downloads your catalogue in small batches in the background, so not every product is on the device from the first minute — see [Product Synchronisation](/products/sync.md) for how this works. ### Why It Matters for Barcode Scanning[​](#why-it-matters-for-barcode-scanning "Direct link to Why It Matters for Barcode Scanning") When you scan a barcode that isn't yet stored locally, the POS goes online to your WooCommerce store, finds that product, and downloads it — so the same scan is instant next time. You don't need to do anything to speed this up: the background catalogue seed fills in the rest of your inventory on its own, and you can check progress in **Store health → Database**. ## F.A.Q.[​](#faq "Direct link to F.A.Q.") Why do I get '0 products found locally' when I scan a barcode? Not all products are on the device right from the start — the POS seeds your catalogue in the background over its first minutes of use. If the product you just scanned isn't stored yet, the scan triggers the POS to look it up online and download it, so it's instant the next time. Does the POS generate and print barcodes? No, not at this time. Our POS is designed to scan and read existing barcodes, but it does not include functionality to create or print them. If you need to generate barcodes for your products, you can use third-party WooCommerce plugins that specialise in barcode creation and printing. Some examples include: * [EAN for WooCommerce](https://wordpress.org/plugins/ean-for-woocommerce/) * [A4 Barcode Generator](https://wordpress.org/plugins/a4-barcode-generator/) Once you have generated barcodes for your products, you can easily scan them at the register to speed up the checkout process in the POS. --- # Meta Data Keys ## What is product meta data?[​](#what-is-product-meta-data "Direct link to What is product meta data?") Every WooCommerce product can carry extra fields beyond its name and price — things like a size, an engraving message, a supplier code, or data added by other plugins. WooCommerce stores these as **meta data**: each entry has a **key** (the field's name, e.g. `engraving`) and a **value** (e.g. `"Happy Birthday"`). ## What the Meta Data Keys setting does[​](#what-the-meta-data-keys-setting-does "Direct link to What the Meta Data Keys setting does") By default, when you add a product to the cart only its standard details are copied. The **Meta Data Keys** setting (Product Panel → Settings) lets you choose which product meta keys should be **copied onto the cart line item** — and therefore saved on the order. For example, adding `engraving` to the list means that whenever you add an engravable product to the cart, its engraving value travels with it onto the order. ## Choosing keys[​](#choosing-keys "Direct link to Choosing keys") Start typing in the Meta Data Keys field: * **Suggestions** are the meta keys found on the products already synced to this device. * If the key you need isn't listed (for example, it only exists on products not yet synced), just type the exact key name and choose **Add "…" as a custom key**. * Selected keys appear as chips; remove one by tapping its ✕. The keys you choose are saved with your other panel settings and apply to both the table and grid (tile) views. ## Tips[​](#tips "Direct link to Tips") * Meta keys are case-sensitive and must match the key stored on the product exactly. * Keys beginning with an underscore (e.g. `_size`) are "hidden"/internal WooCommerce meta. They still work here if that's where your data lives. --- # Search & Filtering Finding the right products quickly is essential for efficient point-of-sale operations. WCPOS provides powerful search and filtering capabilities to help you locate products instantly, even with large inventories. ![Product search and filtering interface](/img/product-search-and-filtering.png) Product search and filtering interface in WCPOS ## Product Search[​](#product-search "Direct link to Product Search") ### Unified Search Field[​](#unified-search-field "Direct link to Unified Search Field") WCPOS features a single search field that simultaneously searches across multiple product attributes: * **Product Name** - Searches the product title and description * **SKU** - Matches product postmeta `_sku` field * **Barcode** - Searches the configured barcode field, which defaults to WooCommerce's GTIN field `_global_unique_id` and can be changed to `_sku` or any custom postmeta key in [Settings](/settings/wp-admin/general.md#barcode-field). Simply type your search term into the "Search Products" field, and the POS will instantly filter results across all these fields. ### Tokenized Search Technology[​](#tokenized-search-technology "Direct link to Tokenized Search Technology") The search functionality uses the [FlexSearch library](https://github.com/nextapps-de/flexsearch) with advanced tokenization capabilities: * **Substring Matching** - Finds your term anywhere inside a word (e.g., searching "berry" finds "blueberry") * **Performance Optimized** - Uses a performance preset for fast search results * **Language Aware** - Adapts to your store's configured language * **Lazy Initialization** - Optimizes memory usage by loading search indexes only when needed Search terms need at least 3 characters From v1.10.0, search matches substrings **inside** words — "berry" finds "blueberry", and "saippua" finds "Kuorintasaippua". The trade-off is a minimum term length: queries shorter than **3 characters** aren't matched against the text index. Short codes still work through the barcode and SKU lookups. Before v1.10.0, matching was prefix-only (search found the start of a word, never the middle). ### How Search Works[​](#how-search-works "Direct link to How Search Works") When you type in the search field, the POS: 1. **Tokenizes** your input into searchable terms 2. **Searches locally** stored product data first for instant results 3. **Queries the server** for the matching products if they aren't local yet, and stores them so the same search is instant next time 4. **Updates results** in real-time as you type Search fetches what you searched for — the rest of your catalogue downloads through the background seed (see [Product Synchronisation](/products/sync.md)), so search stays fast without pulling unrelated data. ## Product Filtering[​](#product-filtering "Direct link to Product Filtering") ### Filter Bar[​](#filter-bar "Direct link to Filter Bar") Below the search field, you'll find interactive filter toggles and dropdown menus that allow you to narrow down products by specific criteria. ### Available Filters[​](#available-filters "Direct link to Available Filters") #### Stock Status[​](#stock-status "Direct link to Stock Status") Filter products based on their inventory status: * **In Stock** - Products with available inventory * **Out of Stock** - Products with zero inventory * **Backorder** - Products available for backorder #### Featured Products[​](#featured-products "Direct link to Featured Products") Toggle to show only products marked as "Featured" in your WooCommerce store. #### On Sale Products[​](#on-sale-products "Direct link to On Sale Products") Filter to display only products currently on sale or with active discounts. #### Category[​](#category "Direct link to Category") Use the category dropdown to filter products by their assigned product categories. This helps you quickly find products within specific departments or product lines. #### Tag[​](#tag "Direct link to Tag") Filter by product tags to find items with specific attributes or characteristics you've defined in your WooCommerce store. ### Using Filters[​](#using-filters "Direct link to Using Filters") * **Toggle Filters** - Click any filter button to activate it (active filters appear highlighted) * **Multiple Filters** - You can combine multiple filters to narrow your search further * **Clear Filters** - Click an active filter again to deactivate it * **Search + Filter** - Use filters together with the search field for precise product location ## Barcode Configuration[​](#barcode-configuration "Direct link to Barcode Configuration") ### Search Fields[​](#search-fields "Direct link to Search Fields") The search functionality automatically includes your configured barcode field. The barcode field used for searching depends on your POS settings configuration. ## F.A.Q.[​](#faq "Direct link to F.A.Q.") What is the \_global\_unique\_id field for barcodes? The `_global_unique_id` field is the GTIN field WooCommerce added to provide better barcode standardization across stores. It is the **default** barcode field in WCPOS. **Key Points:** * **Modern Standard**: This field was designed specifically for global barcode identification (GTIN / UPC / EAN) * **Default**: The POS uses `_global_unique_id` as the barcode field out of the box; you can switch it to `_sku` or any custom meta field in the settings * **Flexibility**: You can configure any product meta field as your barcode field if you're using third-party barcode plugins * **One field per product**: The POS searches a single configured barcode field, and WooCommerce stores one barcode value per product (or per variation). If you need multiple codes on a product, store them in a custom field and point the barcode setting at it * **Rebuilds on change**: Changing the barcode field rebuilds the local catalogue's barcode index, so scans immediately match the newly selected field To configure which field the POS uses for barcodes, visit your POS settings in the WordPress admin area. Why don't I see all my products when I search? The background catalogue seed may not have finished yet. If you don't see a product: 1. **Search for it** - This fetches the matching products from your server directly if they aren't local yet 2. **Check download progress** - **Store health → Database** shows how much of your catalogue is on this device 3. **Check its visibility** - Out-of-stock products are hidden by default, and only standard WooCommerce product types are supported Learn more in our [Product Synchronisation](/products/sync.md) guide. Can I search for partial product names or SKUs? Yes! The tokenized search matches substrings, which means: * Searching "blue" will find products with "blueberry", "blue shirt", etc. * Searching "berry" will also find "blueberry" — the term can appear anywhere in the word * Searching "ABC" will find SKUs like "ABC123", "ABC-XYZ", etc. * You don't need to type complete words or codes (but terms shorter than 3 characters aren't matched) The search is designed to find products quickly with minimal typing. --- # Variable Products Variable products in WooCommerce are products that have multiple options, such as different sizes, colors, or materials. WCPOS provides several ways to work with variable products efficiently. ## Identifying Variable Products[​](#identifying-variable-products "Direct link to Identifying Variable Products") In the Product Panel, variable products are distinguished by: * **Arrow button** () instead of the plus button () used for simple products * **Attribute options** displayed below the product name (e.g., "Colour: Blue, Green, Red") * **"Expand" link** to view all variations inline ## Adding Variable Products to Cart[​](#adding-variable-products-to-cart "Direct link to Adding Variable Products to Cart") ### Method 1: Quick Popover[​](#method-1-quick-popover "Direct link to Method 1: Quick Popover") Click the green arrow button on a variable product to open a popover with dropdown menus for each attribute: 1. Click the button 2. Select options from each dropdown (e.g., Size: Large, Colour: Blue) 3. The matching variation is added to the cart Once your selection narrows to a single variation, the popover shows its stock state beside the add-to-cart button: **"8 in stock"** for tracked stock, **"On Backorder"** for backorderable items, or **"Out of Stock"** (with the button disabled). Variations that don't track their own stock show no number. When the **Show out of stock products** display setting is hiding out-of-stock items, options whose variations are all out of stock appear greyed out and can't be selected. This is the fastest method when you know exactly which variation you need. ### Method 2: Expand Inline[​](#method-2-expand-inline "Direct link to Method 2: Expand Inline") Click the **"Expand"** link on a variable product to show all its variations directly in the product list: 1. Click **Expand** below the product name 2. All variations appear as separate rows beneath the parent product 3. Click the button on any variation to add it to the cart 4. Click **Collapse** to hide the variations again When the **Show out of stock products** display setting is hiding out-of-stock items, out-of-stock variations are excluded from these rows (on-backorder variations remain, since they can still be sold). This method is useful when you want to see all available options, their individual stock levels, and prices. ### Method 3: Barcode Scanning[​](#method-3-barcode-scanning "Direct link to Method 3: Barcode Scanning") Each product variation can have its own unique barcode. When you scan a variation's barcode: * If exactly one variation matches, it's added directly to the cart * If multiple variations share the barcode, the search bar shows matching results * If the matched variation is out of stock and the **Show out of stock products** display setting is hiding out-of-stock items, the scan is refused with an *"out of stock"* message instead of adding to the cart Variation lookups also reach the **server**: if a scanned variation isn't on the device yet, WCPOS looks it up online and downloads it — the same online fallback as for simple products. See [Barcode Scanning](/pos/product-panel/barcode-scanning.md) for more details. ## Variation Information[​](#variation-information "Direct link to Variation Information") Each variation can display: * **Variation attributes** - The specific options for this variation (e.g., "Size: Large, Colour: Blue") * **SKU** - Unique identifier for the variation (may differ from parent product) * **Stock quantity** - Individual stock level for the variation * **Price** - Variations can have different prices than the parent or each other ## Variations in the Cart[​](#variations-in-the-cart "Direct link to Variations in the Cart") When a variation is added to the cart, it displays: * **Product name** from the parent product * **Variation attributes** below the name * **Price** for that specific variation You can edit the line item just like any other product in the cart. ## Tips for Efficient Variation Selection[​](#tips-for-efficient-variation-selection "Direct link to Tips for Efficient Variation Selection") ### Use Barcode Scanning[​](#use-barcode-scanning "Direct link to Use Barcode Scanning") If your variations have individual barcodes (recommended), scanning is the fastest way to add them to the cart. ### Configure Display Options[​](#configure-display-options "Direct link to Configure Display Options") In the Product Panel [Display Settings](/pos/product-panel/.md#display-settings), enable the **Attributes** option to show variation attributes directly in the product list without expanding. ### Keyboard Navigation[​](#keyboard-navigation "Direct link to Keyboard Navigation") When the variation popover is open, you can use keyboard arrow keys to navigate options and Enter to select. ## F.A.Q.[​](#faq "Direct link to F.A.Q.") Why can't I see a specific variation? Check that the variation: * Is published and not in draft status * Is set to "In Stock" or has stock quantity > 0 (if stock management is enabled) * Has all required attributes defined Also ensure you haven't filtered out the product with the "In Stock" filter if the variation is out of stock. How do I add barcodes to individual variations? In WooCommerce, edit the variable product and expand each variation. You can add a unique barcode to each variation's barcode field (typically `_sku` or `_global_unique_id` depending on your configuration). --- # End-of-Day Reconciliation At the end of a shift you close out the till: count the cash, compare it to what the POS says you took, check card totals, and file the record. WCPOS tells you what the drawer *should* hold — the cashier counts it and reconciles manually. Pro Feature The Reports screen used for reconciliation requires [WCPOS Pro](/getting-started/pro-license.md). Without Pro, reconcile from `WP Admin → WooCommerce → Analytics`. ## The short version[​](#the-short-version "Direct link to The short version") 1. **Stop taking sales** so nothing lands mid-count. 2. **Count the drawer** — every denomination. That's your *counted cash*. 3. **Open Reports**, filter to today (and your cashier/store), and read the **Cash** and **Card** figures from the Sales Summary. 4. **Reconcile cash:** *Opening float + cash sales − cash refunds − cash drops* should equal your counted cash. 5. **Reconcile card:** the card terminal's batch total should match the POS card total. Settle the batch if your terminal is manual. 6. **Print the report**, drop the cash, put tomorrow's float back, and sign off. No built-in till sessions WCPOS has no opening-float field, drawer-counting, or automated variance calculation — keep the float and drops on a sheet or spreadsheet at the till. ## Want the full walkthrough?[​](#want-the-full-walkthrough "Direct link to Want the full walkthrough?") The complete walkthrough covers variance handling, multi-cashier and multi-store closes, what to do when a sale lands mid-close, and best practices for an auditable trail. [Full Reconciliation WalkthroughStep-by-step close, variance handling, and multi-cashier/store scenarios](/reports/reconciliation.md) [ReportsThe Reports screen reference — filters, columns, summary panel](/reports/.md) [RefundsIssuing refunds during the shift](/orders/refunds.md) --- # Refunds at the Till Need to give money back at the register? WCPOS lets you refund a WooCommerce order without leaving the POS — full or partial, back to the original payment method or as cash from the till. Pro Feature Issuing refunds from the POS requires [WCPOS Pro](/getting-started/pro-license.md). Without Pro, refund from `WP Admin → WooCommerce → Orders`. ## The short version[​](#the-short-version "Direct link to The short version") 1. **Open the refund form** — from the Orders list, click the three-dot menu on the order and choose **Refund**; or open the order and click **Refund** in the footer. 2. **Set the quantities** — enter a **Refund Qty** for each line (set every line to its full quantity for a whole-order refund, or just a few lines for a partial). Add an optional **Custom Amount** and **Reason** if needed. 3. **Choose where the money goes:** * **Refund to *(gateway)*** — sends the funds back to the original card/wallet, for gateways that support it (e.g. Stripe Terminal, Vipps MobilePay). * **Refund via cash** — record cash handed back from the till. Used automatically for cash sales. 4. **Confirm** — press **Process Refund** and confirm the amount. The order updates immediately. Refunds need a live server connection — unlike checkout, they can't be queued offline. ## Want the full details?[​](#want-the-full-details "Direct link to Want the full details?") The complete guide covers which order statuses can be refunded, how the refund form calculates tax, gateway-vs-cash decision rules, what happens to receipts and order status afterward, and the cashier/store audit trail. [Full Refunds GuideEverything about issuing refunds, gateway vs cash, and what happens afterward](/orders/refunds.md) [Payment GatewaysWhich gateways support refunds back to the original method](/payment/.md) [ReceiptsFiscal vs. live receipts on refunded orders](/receipts/at-checkout.md) --- # Products Management Pro Feature The Products screen requires [WCPOS Pro](/getting-started/pro-license.md). Free users can view and add products to cart from the [POS Product Panel](/pos/product-panel/.md), but cannot edit inventory or prices. The Products screen is a dedicated inventory management interface. Unlike the [POS Product Panel](/pos/product-panel/.md) (which is for selling), this screen is designed for managing your product catalogue. ## Products Screen vs POS Product Panel[​](#products-screen-vs-pos-product-panel "Direct link to Products Screen vs POS Product Panel") | Feature | POS Product Panel | Products Screen | | ---------------- | -------------------- | ------------------ | | **Purpose** | Add products to cart | Manage inventory | | **Stock** | View only | Edit inline | | **Prices** | View only | Edit inline | | **Actions** | Add to cart | Edit, Sync, Delete | | **Available in** | Free + Pro | Pro only | ## Interface Overview[​](#interface-overview "Direct link to Interface Overview") ### Search & Filters[​](#search--filters "Direct link to Search & Filters") At the top of the screen: * **Search bar** - Find products by name, SKU, or barcode * **Filter buttons** - Stock Status, Featured, On Sale, Category, Tag, Brand * **Display settings** () - Configure visible columns ### Product List[​](#product-list "Direct link to Product List") The main area displays your products in a scrollable table: * **Image** - Product thumbnail * **Product name** - With optional SKU, barcode, attributes * **Stock** - Editable stock quantity with "Manage" toggle * **Stock Status** - In Stock (green), Out of Stock (red), Backorder * **Categories** - Product category badges * **Prices** - Current price, regular price, sale price (all editable) * **Actions** - Three-dot menu with Edit, Sync, Delete Sorting and filtering cover your whole store Sorting and filtering run on the **server**, so they apply across your entire catalogue — not just the products already on the device. Sort by name, SKU, stock, price, or date, and the list keeps loading more rows as you scroll, right through the catalogue. Product **search**, by contrast, runs on-device once the catalogue is local, so it returns instantly with no server request. ### Variable Products[​](#variable-products "Direct link to Variable Products") Variable products show: * Attribute options (Colour, Size, etc.) * "Expand" link to view all variations * Individual variation rows with separate stock/prices ### Footer[​](#footer "Direct link to Footer") * **Tax status** - Current tax calculation basis * **Product count** - "Showing X of Y" with sync button (). **Long press** the sync button for the Clear and Refresh option (from v1.10.0 this also clears the screen's search and active filters, so the list comes back unfiltered) ## Key Features[​](#key-features "Direct link to Key Features") ### Inline Stock Editing[​](#inline-stock-editing "Direct link to Inline Stock Editing") Click directly on the stock quantity to edit it: 1. Click the stock number 2. Enter the new quantity 3. Press Enter to save Changes sync to WooCommerce automatically. ### Manage Stock Toggle[​](#manage-stock-toggle "Direct link to Manage Stock Toggle") The "Manage" toggle controls whether WooCommerce tracks inventory for this product: * **On** - Stock levels are tracked and decremented on sales * **Off** - Product is always available (infinite stock) ### Inline Price Editing[​](#inline-price-editing "Direct link to Inline Price Editing") Click on any price field to edit: * **Price** - Current selling price * **Regular Price** - Non-discounted price * **Sale Price** - Discounted price (when on sale) ### Cost of Goods Sold[​](#cost-of-goods-sold "Direct link to Cost of Goods Sold") WooCommerce's Cost of Goods Sold (COGS) feature lets you track the cost price of each product. WCPOS surfaces this data on the Products screen. To view cost prices, enable the **Cost of Goods Sold** column in [Display Settings](#display-settings) (). The column shows the cost price alongside your selling prices, making it easy to review margins at a glance. Pro Feature [WCPOS Pro](/getting-started/pro-license.md) users can **edit** the cost price directly from the Products screen — click the cost value to update it inline, just like stock and price fields. WooCommerce Requirement Cost of Goods Sold must be enabled in your WooCommerce store: go to **WooCommerce > Settings > Advanced > Features** and enable the Cost of Goods Sold option. This requires a recent version of WooCommerce with the Cost of Goods Sold feature enabled. See the WooCommerce documentation for setup details. ### Product Actions[​](#product-actions "Direct link to Product Actions") Click the three-dot menu (⋮) for each product: * **Edit** - Open the product edit modal * **Sync** - Refresh this product from WooCommerce * **Delete** - Remove product from local database note Deleting a product from the POS only removes it **locally** — the product remains in WooCommerce and returns on the next sync. If a product is deleted **in WooCommerce**, the sync removes it from the POS too, so your device stays in step with the store. ## Display Settings[​](#display-settings "Direct link to Display Settings") Click the sliders icon () to customise the Products screen. ![Products Settings](/img/products-page-settings.png) Products Display Settings ### Available Columns[​](#available-columns "Direct link to Available Columns") | Column | Description | Display Options | | ---------------------- | -------------------------------------- | ------------------------ | | **Image** | Product thumbnail | - | | **ID** | WooCommerce product ID | - | | **Product** | Product name | SKU, Barcode, Attributes | | **Type** | Simple, variable, grouped, etc. | - | | **SKU** | Stock Keeping Unit | - | | **Barcode** | Product barcode | - | | **Stock** | Current quantity (editable) | - | | **Stock Status** | In Stock / Out of Stock / Backorder | - | | **Categories** | Product categories | - | | **Tags** | Product tags | - | | **Brands** | Brand info (if plugin active) | - | | **Cost of Goods Sold** | Product cost price (editable with Pro) | - | | **Price** | Current selling price (editable) | Tax info | | **Regular Price** | Non-discounted price (editable) | Tax info | | **Sale Price** | Discounted price (editable) | Tax info | | **Date Created** | When product was created | - | | **Date Modified** | Last modification date | - | | **Actions** | Edit, Sync, Delete buttons | - | ### Restore Default Settings[​](#restore-default-settings "Direct link to Restore Default Settings") Click to reset all display settings to their original defaults. ## Filtering Products[​](#filtering-products "Direct link to Filtering Products") Use the filter buttons to narrow your view: * **Stock Status** - In Stock, Out of Stock, Backorder * **Featured** - Products marked as featured * **On Sale** - Products currently on sale * **Category** - Filter by product category * **Tag** - Filter by product tag * **Brand** - Filter by brand (if using brand plugin) ## Sorting[​](#sorting "Direct link to Sorting") Click any column header to sort by that column. Click again to reverse the sort order. ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [Product SynchronisationHow products sync with WooCommerce](/products/sync.md) [POS Product PanelThe selling interface](/pos/product-panel/.md) [Barcode ScanningSetting up barcode scanning](/pos/product-panel/barcode-scanning.md) --- # POS Only Products POS Only Products is a feature that lets you control whether products appear in your online store, your POS, or both. This is useful when you have different product catalogues for online and in-store sales. ## Overview[​](#overview "Direct link to Overview") When enabled, each product gets a **POS Visibility** setting with three options: | Visibility | Online Store | POS | | -------------------------- | ------------ | ------- | | **POS & Online** (default) | Visible | Visible | | **POS Only** | Hidden | Visible | | **Online Only** | Visible | Hidden | ## When to Use This Feature[​](#when-to-use-this-feature "Direct link to When to Use This Feature") Enable POS Only Products if you need to: * **Sell in-store exclusives** - Products only available when customers visit your physical store * **Hide online-only items from POS** - Digital products, pre-orders, or items that shouldn't be sold in-store * **Manage different catalogues** - Separate product ranges for online and retail channels * **Control promotional items** - In-store-only specials or online-exclusive deals tip If all your products should appear in both channels, you don't need this feature. Leave it disabled for better performance. ## Enabling the Feature[​](#enabling-the-feature "Direct link to Enabling the Feature") 1. Go to **WP Admin > POS > Settings > General** 2. Enable **"Enable POS Only Products"** 3. Save changes For more details on General Settings, see [WP Admin General Settings](/settings/wp-admin/general.md). Performance Impact Only enable this setting if you need it. When enabled, it adds an extra database lookup for every product request, which can impact performance on stores with large catalogues. ## Setting Product Visibility[​](#setting-product-visibility "Direct link to Setting Product Visibility") ### Individual Products[​](#individual-products "Direct link to Individual Products") To set visibility for a single product: 1. Go to **WP Admin → Products** and edit a product 2. In the **Product data** panel, look for **POS Visibility** 3. Select your desired option: * **POS & Online** - Product appears everywhere (default) * **POS Only** - Product hidden from online store * **Online Only** - Product hidden from POS 4. Click **Update** to save ![POS Visibility setting in the product data panel](/img/pos-only-products.png) POS Visibility setting in the Product data panel ### Bulk Editing[​](#bulk-editing "Direct link to Bulk Editing") To change visibility for multiple products at once: 1. Go to **WP Admin → Products** 2. Select the products you want to modify using the checkboxes 3. From the **Bulk actions** dropdown, select **Edit** 4. Click **Apply** 5. In the bulk edit panel, find the **POS Visibility** dropdown 6. Select your desired visibility option 7. Click **Update** ![Bulk editing POS visibility for multiple products](/img/bulk-edit-pos-only-products.png) Bulk editing POS visibility from the Products list ### Variable Products[​](#variable-products "Direct link to Variable Products") For variable products, you can set visibility at both the parent product level and for each individual variation. This gives you fine-grained control - for example, you could show all variations online but only certain colours or sizes in-store. ![POS Visibility settings for individual variations](/img/pos-only-variations.png) Each variation has its own POS Visibility setting ## How It Affects the POS[​](#how-it-affects-the-pos "Direct link to How It Affects the POS") When a product is set to **Online Only**: * It won't appear in the [Product Panel](/pos/product-panel/.md) * It won't be found via search or barcode scanning * It cannot be added to cart in the POS When a product is set to **POS Only**: * It won't appear on your WooCommerce store frontend * It won't be included in online search results * Customers cannot purchase it online note If you've recently changed a product's visibility and it's still appearing (or not appearing) in the POS, try a sync. Long press the sync button and select **"Clear and Refresh"** to reload all product data. ## Common Use Cases[​](#common-use-cases "Direct link to Common Use Cases") #### In-Store Only Gift Cards Physical gift cards that need to be activated at the register: 1. Create the gift card product 2. Set visibility to **POS Only** 3. The card won't appear online but staff can sell it in-store #### Online Pre-Orders Products available for pre-order online but not yet in stock: 1. Create the pre-order product 2. Set visibility to **Online Only** 3. Customers can pre-order online, but it won't clutter the POS #### Wholesale vs Retail If you use the same WooCommerce store for wholesale and retail: 1. Set wholesale-only products to **Online Only** (for B2B portal access) 2. Set retail exclusives to **POS Only** 3. Keep regular products as **POS & Online** ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") Products still appearing after setting to Online Only 1. Open the POS 2. Long press the sync button at the bottom of the Product Panel 3. Select **"Clear and Refresh"** 4. Wait for products to reload Setting not showing on products Make sure the feature is enabled: 1. Go to **WP Admin > POS > Settings > General** 2. Verify **"Enable POS Only Products"** is checked 3. Save settings if you made changes ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [WP Admin General SettingsEnable the feature](/settings/wp-admin/general.md) [Product PanelThe POS product browsing interface](/pos/product-panel/.md) [Product SynchronisationHow products sync between WooCommerce and POS](/products/sync.md) --- # Product Synchronisation WCPOS keeps a local copy of your products on each device, so the catalogue browses and searches instantly and keeps working offline. This guide explains how products get onto the device and how they stay up to date. Changed in v1.10.0 v1.10.0 introduces a new sync engine. If your POS predates v1.10.0, see [What changed in v1.10.0](#what-changed-in-v1100) below. ## How products arrive on the device[​](#how-products-arrive "Direct link to How products arrive on the device") * **A catalogue seed runs in the background.** From first launch, the POS downloads your catalogue in small batches on a schedule, without you doing anything. You can start selling as soon as the first products land — checkout doesn't wait for a complete download. * **What you're looking at downloads on demand.** Searching, filtering by category, or scanning a barcode fetches the matching products directly if they aren't local yet. A search no longer pulls unrelated products along with it — it fetches what you asked for. * **Updates arrive through change checks.** Once a product is local, the POS doesn't re-download it to see if it changed. It polls a lightweight change log (every 60 seconds on the default preset) and fetches only what actually changed — an idle store answers with a single, nearly free "nothing changed" response. ## How big are the batches?[​](#batch-size "Direct link to How big are the batches?") By default the POS requests **50 products at a time**. This is no longer a fixed constant — it's one of two dials set by your sync preset in **Store health → Performance**: | Preset | Check interval | Records per request | | ------------------ | -------------- | ------------------- | | Eco | 5 min | 25 | | Balanced (default) | 60 s | 50 | | Realtime | 10 s | 75 | Small batches exist to protect your server: large pages take real server time to build, and on shared hosting they can slow the storefront or trip rate limits. Choose Eco for modest hosting, Realtime for multi-till shops on strong hosting. See [Store Health](/support/store-health.md#sync-presets) for details. ## Checking download progress[​](#checking-progress "Direct link to Checking download progress") Open **Store health → Database** to see, per collection, how many records are on this device versus on your server, with a coverage bar. The *on server* number is a real server-reported total — while the POS is still confirming it, the row shows *checking…* rather than a guess. A partial products bar simply means the seed hasn't finished; it will keep filling in the background. If a specific product seems missing, search for it — that fetches it directly. tip If a collection seems stuck, use **Clear & re-download** on its row in Store health → Database before reaching for the full [clear all local data](/support/troubleshooting/clear-local-data.md) reset. ## What changed in v1.10.0[​](#what-changed-in-v1100 "Direct link to What changed in v1.10.0") Earlier versions downloaded the catalogue *progressively through use*: each search or scroll pulled another batch of products, and a full poll ran every 5 minutes. That model is retired. In v1.10.0: * The catalogue fills through a scheduled background seed — you don't need to search or scroll to make products download. * A search fetches the products that match it, not an arbitrary next batch. * Change checks run on your chosen preset interval (default 60 seconds) using conditional requests, instead of a fixed 5-minute full poll. * Download progress is visible per collection in **Store health → Database**. Developers can find the full mechanics in [How the Sync Engine Works](/reference/sync-engine.md). ## F.A.Q.[​](#faq "Direct link to F.A.Q.") Do I need to do anything to download my products? No. The catalogue seed downloads your products in the background automatically. Searching or filtering fetches specific products immediately if they aren't local yet, but ordinary browsing is not what completes the download — the background seed is. How quickly do product changes reach the POS? On the default Balanced preset, the POS checks for changes every 60 seconds (checks are slightly randomised so multiple tills don't hit the server together). Only changed products are fetched. If several tills need to see each other's changes faster, use the Realtime preset. I can't see all my products in the POS A few possibilities: * The background seed may simply not have finished — check the products row in **Store health → Database**. * The POS hides out-of-stock items by default. This can be changed in the product display settings. * The WooCommerce REST API only supports the standard product types (simple, variable, grouped, external). Custom product types might not display in the POS. --- # Receipts WCPOS includes a complete template system for receipts, invoices, gift receipts, packing slips, kitchen tickets and more — all managed in **WP Admin → POS → Templates**. Just want to change your receipt? Start at **[Customise Your Receipt](/receipts/customise.md)**. It walks through the three easiest ways to do it — picking a different bundled template, asking AI to tweak one, or editing by hand. ## Template engines[​](#template-engines "Direct link to Template engines") WCPOS supports three template engines. The engine is chosen when you create a template or click **Use Template** on a gallery card, and **cannot be changed afterward** — start a new template if you want to switch engines. #### Logicless HTML (recommended) Mustache-style `{{variable}}` placeholders inside plain HTML. Renders client-side, so receipts **work offline**. Use for browser print and PDF receipts. #### Thermal XML XML templates that produce both a screen preview and **ESC/POS commands** for thermal receipt printers. Same template, two outputs. Use for Epson, Star, and other thermal printers. #### Legacy PHP Server-side PHP templates using WooCommerce functions. Kept for backward compatibility with existing `yourtheme/woocommerce-pos/receipt.php` overrides. Requires a server connection to render. ## Template gallery[​](#template-gallery "Direct link to Template gallery") The gallery ships with ready-made templates you can use as-is or customise. Filter by **category** (Receipt, Invoice, Gift Receipt, Kitchen Ticket, Quote / Purchase Order), **format** (HTML / Thermal), and **direction** (LTR / RTL); preview with your store's real data. Each card's footer has a **Preview** link and a primary **Use Template** button — clicking Use Template creates an editable copy in *Your Templates*. ### HTML templates[​](#html-templates "Direct link to HTML templates") For browser print and PDF receipts. Render client-side, so they work offline. #### Standard Receipt **HTML** · Default receipt — logo, store identity, items, totals, payment. #### Standard Receipt (RTL) **HTML · RTL** · Right-to-left counterpart for Arabic, Hebrew, Persian, Urdu. #### Minimal / Modern **HTML** · Same essentials as Standard, packed into less vertical space. #### Detailed Receipt **HTML** · Full tax invoice — SKU column, unit price, per-rate tax breakdown, addresses. #### Gift Receipt **HTML** · Items only, prices hidden. Includes gift message and return policy. #### Invoice **HTML** · Full-page A4/Letter invoice with optional "How to pay" panel for unpaid orders. #### Packing Slip **HTML** · Warehouse companion — items + quantities, ship-to, no prices. #### Quote / Estimate **HTML** · Pre-sale document with pricing and terms — no payment section. #### Narrow Receipt **HTML** · Monospace receipt for narrow paper or HTML-capable thermal printers. ### Thermal templates[​](#thermal-esc-pos-templates "Direct link to Thermal templates") For Epson, Star, and other thermal receipt printers. #### Simple Thermal Receipt (58mm) **Thermal · 58mm** · Clean 58mm thermal layout. #### Simple Thermal Receipt (80mm) **Thermal · 80mm** · Clean 80mm thermal layout — most common. #### Simple Thermal Receipt 80mm (RTL) **Thermal · 80mm · RTL** · RTL counterpart for 80mm. Needs a printer with an Arabic codepage (CP864 / Windows-1256). #### Detailed Thermal Receipt (58mm) **Thermal · 58mm** · Kitchen-sink 58mm — addresses, tax breakdown, refunds, payments, terms, barcode. #### Detailed Thermal Receipt (80mm) **Thermal · 80mm** · Kitchen-sink 80mm — addresses, tax breakdown, refunds, payments, terms, barcode. #### Kitchen Ticket **Thermal** · Items only, large font, no pricing — for prep stations. ### Third-party document templates[​](#third-party-document-templates "Direct link to Third-party document templates") If **PDF Invoices & Packing Slips for WooCommerce** by WP Overnight is active, WCPOS also exposes **Invoice (WP Overnight)** and **Packing Slip (WP Overnight)** in the receipt template list. These server-rendered HTML templates delegate to WP Overnight's document API, reusing the invoice and packing-slip numbering, layout, branding, legal/tax fields, and template customisations configured in that plugin. They are available only while the WP Overnight plugin is active and require a server connection to render. Use WCPOS's bundled HTML or thermal templates when offline printing is required. ### Adaptive tax display[​](#adaptive-tax-display "Direct link to Adaptive tax display") Most bundled templates (Standard, Standard RTL, Minimal/Modern, Narrow, Invoice, Quote, Thermal Simple variants) **adapt automatically to your WooCommerce tax-display setting**: * **Tax-inclusive stores** (EU/UK/AU) see gross prices with a "Tax included" line. * **Tax-exclusive stores** (US/CA) see net prices with tax added as a separate line. * The grand total always shows the gross amount actually charged. The **Detailed** family is a formal tax invoice and always itemises tax with tax-exclusive lines plus an explicit breakdown, regardless of the store setting. ## How it works[​](#how-it-works "Direct link to How it works") 1. **Add a template** — click **Use Template** on a gallery card, or create your own from scratch. 2. **Customise it** using the in-app editor with live preview, or paste it into ChatGPT / Claude and ask for the changes you want. 3. **Activate it** — flip the **Active** toggle in *Your Templates*. Every active receipt template appears in the receipt-screen dropdown at the till. 4. **Print or display** — receipts open after checkout with options to print, email, or view on screen. Your templates also work beyond the till: online customers can [download receipts from My Account](/receipts/storefront.md) rendered with the same design. Templates render against a standardised [receipt data payload](/receipts/receipt-data.md) with sections for store info, line items, totals, tax, payments, refunds, and more. Currency fields all include pre-formatted `_display` variants (e.g., `$29.99` instead of `29.99`). ## Pro features[​](#pro-features "Direct link to Pro features") With [WCPOS Pro](/getting-started/pro-license.md), each store can have its own template assignments, branding (logo, address, contact details), and template ordering — useful for multi-location operations where each shop prints its own letterhead. ## In this section[​](#in-this-section "Direct link to In this section") [Customise Your ReceiptThe easiest way to change how your WCPOS receipt looks — pick a different template, ask AI to tweak it, or edit it by hand.](/receipts/customise.md) [HTML TemplatesCreate and customise logicless HTML receipt templates using Mustache-style placeholders.](/receipts/html-templates.md) [Thermal TemplatesCreate XML-based receipt templates for ESC/POS thermal printers with Epson and Star support.](/receipts/thermal-templates.md) [Receipt DataComplete reference for the canonical data contract available in WCPOS receipt templates.](/receipts/receipt-data.md) [Cloud PrintingPrint WCPOS receipts to printers that aren't attached to the till — Star Online, Star CloudPRNT, Epson Server Direct Print, and PrintNode.](/receipts/cloud-printing.md) [ReceiptsPrint and email receipts in WCPOS, including printer setup and receipt customisation options.](/receipts/at-checkout.md) [Online Store ReceiptsLet online customers download receipts and invoices from My Account, rendered with your custom WCPOS template.](/receipts/storefront.md) --- # Receipts After successfully processing a payment, the receipt modal displays. This shows a summary of the completed order and provides options to print or email the receipt. ## Receipt Contents[​](#receipt-contents "Direct link to Receipt Contents") The receipt displays: ### Store Information[​](#store-information "Direct link to Store Information") * **Store name** * **Address** * **Phone number** * **Email** * **Website** * **Logo** (if configured) ### Receipt Header[​](#receipt-header "Direct link to Receipt Header") * **Receipt type** (e.g., "Tax Receipt") * **Order number** * **Date and time** * **Cashier name** * **Payment method** ### Order Details[​](#order-details "Direct link to Order Details") * **Line items** with: * Product name * Variation attributes (if applicable) * Quantity * Price * Total ### Totals[​](#totals "Direct link to Totals") * **Subtotal** * **Tax** (if applicable) * **Total** * **Amount Tendered** (for cash) * **Change** (for cash) ### Customer Information[​](#customer-information "Direct link to Customer Information") * **Billing address** * **Shipping address** (if different) ## Receipt Actions[​](#receipt-actions "Direct link to Receipt Actions") ### Close[​](#close "Direct link to Close") Dismiss the receipt modal and return to the POS. ### Email Receipt[​](#email-receipt "Direct link to Email Receipt") Send the receipt to the customer's email address: 1. Click **Email Receipt** 2. Confirm the email address 3. The receipt is sent via WooCommerce's email system The customer must have an email address associated with the order. ### Print Receipt[​](#print-receipt "Direct link to Print Receipt") Print a physical copy of the receipt: 1. Click **Print Receipt** 2. Your browser's print dialogue opens 3. Select your receipt printer and print Receipt Printers WCPOS works with any printer accessible from your browser. For best results, use: * A dedicated receipt printer (thermal printers are common) * Configure paper size in your printer settings * Set up a print preset for quick printing ## Automatic Receipt Options[​](#automatic-receipt-options "Direct link to Automatic Receipt Options") In the [Cart Display Settings](/pos/cart/.md#display-settings), you can configure: * **Automatically show receipt after checkout** - Opens the receipt modal immediately after payment * **Automatically print receipt after checkout** - Triggers print automatically when receipt is shown These options speed up high-volume checkout workflows. ## Customising Receipts[​](#customising-receipts "Direct link to Customising Receipts") Receipt appearance is controlled by templates in WordPress: `WP Admin > POS > Templates` See [Receipt Templates](/receipts/.md) for details on customising: * Store information display * Logo and branding * Layout and formatting * What information to include ## Reprinting Receipts[​](#reprinting-receipts "Direct link to Reprinting Receipts") To reprint a receipt for a past order: 1. Go to the [Orders screen](/orders/.md) (Pro feature) 2. Find the order 3. Click to open the order 4. Use the receipt option to print again ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [Receipt TemplatesCustomise receipt appearance](/receipts/.md) [Cloud PrintingPrint to Star, Epson, and PrintNode printers](/receipts/cloud-printing.md) [Cart SettingsAuto-show and auto-print options](/pos/cart/.md#display-settings) [OrdersReprint past receipts (Pro)](/orders/.md) --- # Cloud Printing Cloud printing lets WCPOS send receipts to a printer that isn't directly connected to the device running the till. Set it up once in WP Admin and your orders print to a kitchen printer, a back-office printer, or a printer in another room — without each device having to discover and pair with the hardware itself. ## What is cloud printing?[​](#what-is-cloud-printing "Direct link to What is cloud printing?") With **local printing**, the device running the POS talks straight to the printer over USB, Bluetooth, or the local network. That's the right choice when the printer sits next to the till — see [Printer Setup](/hardware/printers/.md) for connecting USB, Bluetooth, and network printers on the same device. **Cloud printing** is for everything else: a printer in a different location, on a different network, or one you want every device to share without configuring it on each one. There are two delivery models: * **Polling printers.** The printer reaches out to WCPOS over the internet on a schedule, asks "do you have anything for me?", and pulls down any waiting jobs. WCPOS never connects to the printer — the printer always starts the conversation. This is how **Star CloudPRNT** and **Epson Server Direct Print** work. * **Hosted relay providers.** WCPOS submits the print job to a hosted service, and that service delivers it to the printer. This is how **Star Online** and **PrintNode** work. Star Online delivers to Star CloudPRNT printers registered in your stario.online account; PrintNode delivers through its desktop client to almost any printer that computer can already print to. Why a printer that polls? A polling printer doesn't need an open port, a static IP, or any firewall changes — it only ever makes outbound requests. That makes it ideal for a printer at a remote site or behind a router you don't control. The trade-off is a short delay: the printer only prints when its next poll comes around. ## Choosing a provider[​](#providers "Direct link to Choosing a provider") Pick the provider that matches your hardware. #### Star CloudPRNT For Star thermal printers running the **CloudPRNT** firmware. The printer polls WCPOS and pulls jobs. Receipts are rendered to the printer's native commands. Needs a thermal template. #### Star Online For Star printers registered in a **stario.online** account. WCPOS submits Star Document Markup to Star's hosted service, and the printer collects it from Star Online. Needs a thermal template. #### Epson Server Direct Print For Epson ePOS printers that support **Server Direct Print**. The printer polls WCPOS and pulls jobs as ePOS-Print XML. Needs a thermal template. #### PrintNode Works with virtually any printer your computer can print to, on any OS, via the **PrintNode desktop client**. WCPOS submits a PDF, so you can use any template — including full-page HTML invoices. | Provider | Hardware | How jobs flow | Templates | | ----------------------------- | -------------------------------------------- | ------------------------------------------------- | ------------ | | **Star CloudPRNT** | Star thermal printer with CloudPRNT firmware | Printer polls WCPOS | Thermal only | | **Star Online** | Star printer registered in stario.online | WCPOS submits Star Document Markup to Star Online | Thermal only | | **Epson Server Direct Print** | Epson ePOS printer with Server Direct Print | Printer polls WCPOS | Thermal only | | **PrintNode** | Any OS-connected printer + PrintNode client | WCPOS submits a PDF to PrintNode | Any template | ## WCPOS Cloud Print — the relay[​](#relay "Direct link to WCPOS Cloud Print — the relay") When you set up a **polling** printer (Star CloudPRNT or Epson Server Direct Print), the poll URL WCPOS gives you points at **cloudprint.wcpos.com**, not at your own site. That's **WCPOS Cloud Print** — a free relay run by WCPOS that sits between your printer and your store. **Why it exists.** Receipt printers run small, rarely-updated firmware. Many can't complete a secure connection to a store on modern hosting: newer TLS versions, newer certificate authorities, or a CDN/firewall in front of the site (Cloudflare is a common culprit) will refuse the printer — or be refused by it. The symptom is a printer stuck on **Waiting** forever even though every setting is correct. The relay presents printers with a connection that older firmware can always negotiate, and passes their traffic through to your store. **How it works:** * Your site connects to the relay **automatically** the first time you open the Cloud Print settings — there's nothing to enable or configure. * The printer polls `cloudprint.wcpos.com`; the relay forwards the request to your store and returns your store's answer. Print jobs pass **through** the relay — they are never stored on it. * The relay absorbs most idle polling, so an idle printer costs your site about one request per minute instead of one every few seconds. * If your site can't connect to the relay (for example, a local development site the relay can't reach), WCPOS automatically falls back to direct-to-site URLs. Prefer a direct connection? Every printer's setup screen has an **Advanced** disclosure showing the direct-to-site URL. Use it if you know your hosting is printer-friendly, or if you'd rather not route jobs through the relay. Developers can switch the relay off site-wide with one line: ``` add_filter( 'woocommerce_pos_cloud_print_relay_enabled', '__return_false' ); ``` **What the relay can see.** Connecting shares your site URL with wcpos.com, and print jobs — receipt contents, which include order details — transit the relay on their way to the printer. Nothing is retained. Full details are in the [privacy policy](https://wcpos.com/privacy). ## Setting up a cloud printer[​](#setup "Direct link to Setting up a cloud printer") Cloud printers are configured once in WP Admin and shared across every device — unlike local printers, which are stored per device. Go to **WP Admin > POS > Settings > Cloud Print** and click **Add printer**. Give it a **name** (for example "Kitchen" or "Back office"). WCPOS derives a stable **printer ID** from the printer automatically — it never changes, so it's safe to reference from a printer's firmware configuration. After the printer exists, configure the provider end. ### Star or Epson (polling printers)[​](#setup-polling "Direct link to Star or Epson (polling printers)") 1 #### Add the printer in WCPOS In **WP Admin > POS > Settings > Cloud Print**, add a printer and choose **Star CloudPRNT** or **Epson Server Direct Print** as the provider. WCPOS generates a **poll URL** and a **one-time token** for that printer. 2 #### Copy the poll URL and token Copy the generated poll URL and token. The URL normally points at **cloudprint.wcpos.com** — that's the [WCPOS Cloud Print relay](#relay), and it's what you want; the direct-to-site URL sits behind the **Advanced** disclosure. The **token is shown only once** — if you lose it, regenerate a new one from the printer card and update the printer with the new value. 3 #### Enter them in the printer's configuration Open the printer's configuration page — the **CloudPRNT** settings for Star, or the **Server Direct Print** settings for Epson — and paste in the poll URL and token. Set the poll interval if the printer asks for one (a few seconds is typical). Save and reboot the printer if required. Within a poll cycle the printer checks in, and its status in WCPOS changes from **Waiting** to **Connected**. ### PrintNode[​](#setup-printnode "Direct link to PrintNode") 1 #### Install the PrintNode desktop client On a computer that can already print to your target printer, install the **PrintNode client** and sign in. The client must stay running and online for jobs to print. 2 #### Get a PrintNode API key In your PrintNode account, create an **API key**. This is what lets WCPOS submit jobs to your PrintNode account. 3 #### Enter the API key in WCPOS Add a printer in **WP Admin > POS > Settings > Cloud Print**, choose **PrintNode** as the provider, and paste in the API key. WCPOS uses it to fetch the list of printers registered to your PrintNode account. 4 #### Select the printer Choose the target printer from the list of printers reported by the PrintNode client, then save. WCPOS will submit jobs for this printer to PrintNode, and the client prints them. ### Star Online[​](#setup-star-online "Direct link to Star Online") Use Star Online when your Star printer is already registered to a **stario.online** account and you want Star's hosted service to handle delivery. 1 #### Get the CloudPRNT URL In stario.online, open **Device Groups** and copy the group's **CloudPRNT URL**. It should look like `https://device.stario.online/cloudprnt/...` or `https://eu-device.stario.online/cloudprnt/...`. 2 #### Create an API key with permissions In stario.online, create an API key for WCPOS. The key must have permission to list devices and print to them. At minimum, enable: * **EnumDevices** — required when WCPOS fetches the device list * **ViewDevice** — used for device status checks * **PrintToDevice** — required to submit print jobs * **ViewDeviceGroups** — recommended for group lookup and diagnostics An API key can exist and still fail if these permissions are not enabled. 3 #### Enter the URL and API key in WCPOS Add a printer in **WP Admin > POS > Settings > Cloud Print**, choose **Star Online** as the provider, then paste the CloudPRNT URL and API key. Click **Fetch my devices**. 4 #### Select the Star device Choose the printer from the device list and save. WCPOS stores the API key server-side and uses the selected device's access identifier when submitting jobs to Star Online. ## Auto-print rules[​](#auto-print "Direct link to Auto-print rules") Auto-print rules decide what prints where, automatically — written as plain sentences. A rule is **scope × printer × template**, plus **when** it fires and **how many copies** to print, for example: > Print **every order** to **Kitchen** using **Kitchen Ticket**, **once paid**, **×2**. A rule can trigger **when the order is created** or **only once it's paid** — so a kitchen ticket can fire the moment an order is placed while a customer receipt waits for payment — and you can set the **number of copies** when a station needs more than one. When a matching order reaches the chosen trigger, WCPOS renders the chosen **template** server-side into the format the printer needs and queues it — there's nothing for the cashier to do. Template compatibility matters Star and Epson printers can only use **thermal** templates, because the job has to be rendered to the printer's native command language (Star Document Markup or ESC/POS for Star, ePOS-Print for Epson). PrintNode can use **any** template — thermal or full-page HTML — because the job is rendered to a **PDF**. If a template doesn't appear as an option for a printer, it's because the printer can't render that format. See [Thermal Templates](/receipts/thermal-templates.md) for creating thermal layouts. ## Per-store printers (Pro)[​](#per-store-printers "Direct link to Per-store printers (Pro)") Pro Feature Per-store print routing requires [WCPOS Pro](/getting-started/pro-license.md) and a [multi-store](/stores/.md) setup. By default, auto-print rules are global — every store shares them. With Pro, you can give an individual store its **own** cloud-print rules so its orders print to its own printers (a kitchen ticket at one location shouldn't print in another). Edit a store under **POS → Stores**, open its **Cloud Printing** section, and **Add rule**. Each rule is: * **Printer ID** — the stable ID of the cloud printer to send to * **Scope** — **POS orders only** (default), **Online orders only**, or **Every order** * **Format** — **StarPRNT** (default), **ESC/POS**, **Epson ePOS-Print**, or **HTML** When an order belongs to a store that has its own rules, WCPOS routes it to that store's printers. If a store has **no** rules of its own, it **falls back to the global** auto-print rules — so you only need to configure the stores that differ. ## Manual printing[​](#manual "Direct link to Manual printing") You don't have to wait for an auto-print rule. From the **checkout / receipt screen**, a cashier can send a receipt to a cloud printer on demand — handy for reprints or for routing a one-off ticket to a specific printer. How the receipt is produced depends on the printer: * **Star CloudPRNT** — the receipt is rendered **on the device** and handed to the printer through CloudPRNT. * **Star Online, Epson, and PrintNode** — the receipt is rendered **on the server** from the selected order and template, then delivered to the printer or hosted relay. Rendering fallbacks for stubborn printers **Star CloudPRNT** negotiates the media type with the printer and falls back to plain text (`text/plain`) when a printer won't accept the richer format. For Star printers whose firmware can't decode StarPRNT commands, WCPOS can render the receipt **server-side as a PNG image** and send that instead — so the receipt still prints rather than failing. ## The print queue[​](#print-queue "Direct link to The print queue") Every job for a cloud printer sits in a queue on your site until the printer collects it (polling printers) or the provider confirms delivery. **WP Admin > POS > Settings > Cloud Print** shows the queue below your printers: * **Filter** by printer or by status — **Waiting**, **Printing**, **Printed**, **Failed**, **Cancelled** — with live counts. * Each row shows how long the receipt has been **waiting** and links to the WooCommerce **order** it prints. * **Cancel** waiting jobs one at a time, in bulk, or for a whole printer at once. **Retry** re-queues a failed job. If a printer has waiting jobs but hasn't collected anything for more than a few minutes, a **warning banner** names the printer, shows how many receipts are backed up and for how long, and offers **Cancel all** — a backlog can never build up silently while a printer is unplugged. ## Test print & connection status[​](#status "Direct link to Test print & connection status") Each printer card has a **Test print** button that sends a short diagnostic so you can confirm the printer is reachable and the format is right before relying on it for real orders. The card also shows a live status: | Provider | Status | Meaning | | -------------------------- | ------------- | ------------------------------------------------------------------------ | | **Star CloudPRNT / Epson** | **Waiting** | The printer hasn't checked in yet — WCPOS is waiting for its first poll. | | **Star CloudPRNT / Epson** | **Connected** | The printer polled WCPOS recently and is collecting jobs. | | **Star Online** | **Online** | Star Online reports the selected device is available. | | **Star Online** | **Offline** | Star Online reports the selected device is not available. | | **Star Online** | **Unknown** | WCPOS could not confirm the device status from Star Online. | | **PrintNode** | **Online** | The PrintNode service reports the client and printer are available. | | **PrintNode** | **Offline** | PrintNode reports the client or printer is unavailable. | ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") Printer stuck on Waiting A polling printer that never leaves **Waiting** has never successfully reached WCPOS. Check: * The **poll URL and token** in the printer's firmware exactly match what WCPOS generated. A single wrong character means every poll is rejected — regenerate the token in WCPOS and re-enter it if you're unsure. * The printer can actually **reach your site** over the internet (correct DNS, no firewall blocking outbound HTTPS, valid SSL certificate on your store). * **Polling is enabled** in the printer's CloudPRNT / Server Direct Print configuration, with a sensible interval. Reboot the printer after changing its settings. * If you entered the **direct-to-site URL** (from the Advanced disclosure) and the printer still won't connect, switch to the standard **cloudprint.wcpos.com** URL — many printers can't negotiate a secure connection with modern hosting, which is [exactly what the relay fixes](#relay). Why does my printer URL point to cloudprint.wcpos.com? That's [WCPOS Cloud Print](#relay), the free relay that gives printers a connection their firmware can always negotiate and passes their print jobs through to your store. It's on automatically, jobs are never stored on it, and the direct-to-site URL is always available under the printer's **Advanced** disclosure if you prefer. I set my printer up before the relay existed — do I need to change anything? No — URLs already saved in a printer's configuration keep working. If that printer is **stuck on Waiting**, though, its firmware is likely one that can't connect to your hosting directly: open **Setup & token** on the printer card, regenerate the token, and enter the new **cloudprint.wcpos.com** URL and token in the printer's configuration. Star Online says the API key is unauthorised or forbidden Star Online separates **authentication** from **permissions**: * **401 / authentication failed** means the API key itself was not accepted. Check that the key was copied correctly, has not been revoked, and belongs to the expected Star Online account/region. * **403 / forbidden** means the API key was accepted but is not authorised for the requested action. Edit the key in stario.online and enable the required permissions, especially **EnumDevices** for **Fetch my devices** and **PrintToDevice** for printing. If **Fetch my devices** succeeds but no printers appear, check the stario.online **Device Groups** page. The group must contain at least one connected device, and the CloudPRNT URL in WCPOS must point to that same group. PrintNode job never prints The job reached PrintNode but didn't come out of the printer. Check: * The **PrintNode desktop client is running and online** on the computer connected to the printer. If the computer is asleep or the client is closed, nothing prints. * You selected the **correct printer** in WCPOS — the name must match the printer the client reports. * The **API key is valid** and hasn't been revoked. Re-enter it if PrintNode shows the printer as Offline. My template isn't selectable for a Star or Epson printer Only **thermal** templates work on Star and Epson cloud printers, because the receipt has to be rendered to ESC/POS or ePOS-Print commands. HTML and full-page templates can't be expressed in those formats, so they're hidden for these printers. Either choose a [thermal template](/receipts/thermal-templates.md), or use a **PrintNode** printer — PrintNode renders to PDF, so it can print any template. ## Related Documentation[​](#related-documentation "Direct link to Related Documentation") [Printer SetupConnect a printer on the same device or network](/hardware/printers/.md) [TemplatesThe receipt template system](/receipts/.md) [Thermal TemplatesBuild ESC/POS layouts for Star and Epson printers](/receipts/thermal-templates.md) --- # Customise Your Receipt If you want to change how your receipt looks, you have three options. Pick the easiest one that does what you need — most stores never have to look past the first. ## Three ways to customise[​](#three-ways-to-customise "Direct link to Three ways to customise") #### 1. Pick a different template Use one of the ready-made templates in the gallery. **No code at all.** Best for: a different layout, hiding prices, an A4 invoice, a kitchen ticket. #### 2. Ask AI to tweak it Paste the template into ChatGPT or Claude and describe what you want. **No coding skills needed** — you describe it in plain English. Best for: small tweaks like wording, colours, or moving things around. #### 3. Edit it by hand The in-app editor lets you change the template directly. Best for: precise control, or if you already know HTML. All three start in the same place: **WP Admin → POS → Templates**. The page has two parts — **Your Templates** at the top (the ones you're using right now) and the **Template Gallery** below it (the starter library). ## Option 1 — Pick a different template[​](#option-1--pick-a-different-template "Direct link to Option 1 — Pick a different template") This is the easiest path and covers most needs. 1 #### Open the template gallery In WP Admin go to **POS → Templates**. Scroll past *Your Templates* to the **Template Gallery** section — that's the starter library. 2 #### Browse and preview Filter by **category** (Receipt, Invoice, Gift Receipt, Kitchen Ticket, Quote / Purchase Order), **format** (HTML for browser print, Thermal for thermal printers), or **direction** (Left-to-right or Right-to-left). Click any card's thumbnail — or the **Preview** link in its footer — to open a live preview with your store's real data. 3 #### Use it Click **Use Template** on the card. WCPOS makes you an editable copy and adds it to **Your Templates** at the top of the page. Flip the **Active** toggle on the row to start using it on receipts; drag the row's grip handle to reorder. You can have several active at once — the cashier picks at the till. Use Template never replaces anything Clicking **Use Template** always creates a fresh copy. The original gallery template is left untouched, so you can come back and pick a different starting point any time. If multiple receipt templates are active, the receipt screen shows a dropdown so the cashier can switch between them on the fly. ### The bundled templates[​](#the-bundled-templates "Direct link to The bundled templates") | Template | Format | What it's for | | ------------------------------------------ | ------- | ---------------------------------------------------------------------------- | | **Standard Receipt** | HTML | Default — logo, items, totals, payment. Covers most stores | | **Standard Receipt (RTL)** | HTML | Same as Standard, mirrored for Arabic / Hebrew / Persian / Urdu | | **Minimal / Modern** | HTML | Same info as Standard, packed into less vertical space | | **Detailed Receipt** | HTML | Full tax invoice — SKU column, unit price, per-rate tax breakdown, addresses | | **Gift Receipt** | HTML | Items only — prices hidden. Includes gift message and return policy | | **Invoice** | HTML | Full-page A4/Letter invoice. Adds a "How to pay" panel for unpaid orders | | **Packing Slip** | HTML | Warehouse companion — items + quantities, ship-to, no prices | | **Quote / Estimate** | HTML | Pre-sale document with pricing and terms — no payment section | | **Narrow Receipt** | HTML | Monospace receipt for narrow paper or HTML-capable thermal printers | | **Simple Thermal Receipt (58mm)** | Thermal | Clean 58mm thermal layout | | **Simple Thermal Receipt (80mm)** | Thermal | Clean 80mm thermal layout — most common | | **Simple Thermal Receipt 80mm (RTL)** | Thermal | RTL counterpart for 80mm. Requires a printer with an Arabic codepage | | **Detailed Thermal Receipt (58mm / 80mm)** | Thermal | Adds tax breakdown, addresses, refunds, payments, terms, barcode | | **Kitchen Ticket** | Thermal | Items only, large font, no prices — for prep stations | Most of the bundled templates **adapt to your store's tax settings automatically** — tax-inclusive stores see gross prices and a "Tax included" line; tax-exclusive stores see net prices with tax added as a separate line. The **Detailed** family always shows a full tax breakdown regardless of the setting. ### WP Overnight invoice and packing slip templates[​](#wp-overnight-invoice-and-packing-slip-templates "Direct link to WP Overnight invoice and packing slip templates") If your site also uses [PDF Invoices & Packing Slips for WooCommerce](https://wordpress.org/plugins/woocommerce-pdf-invoices-packing-slips/) by WP Overnight, WCPOS automatically adds two extra templates to **Your Templates**: | Template | Format | What it's for | | ------------------------------- | -------------------- | ---------------------------------------------------------------------- | | **Invoice (WP Overnight)** | Server-rendered HTML | Uses WP Overnight's configured invoice document for the POS order | | **Packing Slip (WP Overnight)** | Server-rendered HTML | Uses WP Overnight's configured packing-slip document for the POS order | These templates do not copy WCPOS's built-in invoice or packing-slip layouts. They ask WP Overnight to render the document for the POS order, so your existing invoice numbers, branding, legal/tax fields, and WP Overnight template customisations stay consistent between online and in-store orders. They appear only while the WP Overnight plugin is active. The output opens as HTML in the WCPOS print screen rather than as a separate PDF download. Because the document is rendered on the server, the POS needs a connection to your site when printing these templates; use the bundled HTML or thermal templates for offline printing. ## Per-store assignments[​](#per-store-assignments "Direct link to Per-store assignments") If you have more than one [store](/stores/.md) (Pro), each store can have its **own template selection and ordering**, separate from the site-wide defaults. The cafe down the road can run a small thermal receipt with a different logo and address; the warehouse can use a packing slip; the main shop can keep the standard receipt — all from the same template gallery. Set it up from **WP Admin → POS → Stores**, then open the store you want to configure. The **Edit Store** page has a **Receipt Templates** section with a *"Store specific receipt templates"* toggle: * **Toggle off** *(default)* — the store inherits the site-wide template list from the main **POS → Templates** page. * **Toggle on** — the store gets its own template selection and ordering, separate from the site-wide defaults. Drag-handle reorder works the same way. The same Edit Store page is also where each store's **letterhead** lives (logo, address, contact details, and the *Receipt Messages* block — Complimentary Close, Returns Policy, Footer). The bundled templates pull from these per-store fields, so a single "Standard Receipt" template can carry different branding at different locations. When a cashier signs in at a store, only that store's active templates appear in the receipt dropdown. Site-wide vs per-store The **Templates** page in WP Admin sets the default for the whole site. The per-store override exists so a single template (e.g. a Standard Receipt) can carry different branding at different locations, or so one location can use a layout the others don't. If all your stores want the same templates, just leave per-store assignments empty and the site-wide defaults apply. ## Option 2 — Ask AI to tweak it[​](#option-2--ask-ai-to-tweak-it "Direct link to Option 2 — Ask AI to tweak it") If the gallery is close but not quite right, an AI assistant can change it for you in minutes — and you don't need to know HTML. 1 #### Copy the template Open the template you want to start from in **WP Admin → POS → Templates**, click into the editor, and select all of the text on the left side (Ctrl/Cmd + A). Copy it. 2 #### Paste it into ChatGPT or Claude Open [ChatGPT](https://chat.openai.com) or [Claude](https://claude.ai). Paste the template, then write what you want, in plain English: 3 #### Describe what to change Tell the AI exactly what you want. Examples that work well: * *"Make the store name bigger and centered."* * *"Add a thank-you message in italic at the bottom."* * *"Hide the customer name. Add the phone number underneath the order number instead."* * *"Change the barcode to a QR code that links to my returns page."* * *"Add a tagline 'Family-owned since 1987' under the store name."* The AI will hand you back a modified template. 4 #### Paste it back Copy the AI's response. Back in the WCPOS template editor, select all (Ctrl/Cmd + A), paste the new version, and click **Update**. The preview on the right refreshes so you can see what happened. If it doesn't look right, ask the AI to fix it — describe what went wrong. Best practice Every click of **Use Template** in the gallery makes a fresh editable copy, so the original stays safe. If you're experimenting, you can use the same gallery template more than once — rename your copies *(Receipt v1, Receipt v2)* and toggle between them while you decide. What about variables? The bits like `{{store.name}}` and `{{order.number}}` are **placeholders** for your real data. The AI understands these — you don't need to. If you want to know every placeholder available, see the [Receipt Data Reference](/receipts/receipt-data.md). ## Option 3 — Edit it by hand[​](#option-3--edit-it-by-hand "Direct link to Option 3 — Edit it by hand") If you know a bit of HTML (or you're working with a developer), you can edit the template directly in the in-app editor. The editor has live preview, syntax highlighting, a searchable field picker, undo/redo, and find-and-replace. Choose your engine: * **[HTML Templates](/receipts/html-templates.md)** — Mustache-style `{{variable}}` placeholders. Renders client-side, works offline. **Recommended for most stores.** * **[Thermal Templates](/receipts/thermal-templates.md)** — XML for ESC/POS thermal printers. Same template produces both the screen preview and the printer output. * **[Receipt Data Reference](/receipts/receipt-data.md)** — Every placeholder you can use, grouped by section. Legacy PHP templates If you used to override the receipt with a PHP file in your theme (`yourtheme/woocommerce-pos/receipt.php`), that still works. It's now labelled **Legacy PHP Template** in the gallery, and it sits alongside the new logicless and thermal engines. The WP Overnight integration also uses the server-rendered path because the third-party document API renders HTML on the server. New customisations should use the gallery or the in-app editor instead — they work offline, preview live, and don't need a server round-trip. ## Common customisations[​](#common-customisations "Direct link to Common customisations") Quick answers to the questions we get most often. How do I add my store logo? Logos come from your store settings, not the template itself. Go to **WP Admin > POS > Settings > Stores**, edit your store, and upload a logo there. Every bundled template that shows a logo will use it automatically. If you want to change *where* the logo appears in the template, edit the template and move the `{{#store.logo}}{{/store.logo}}` block to where you want it. How do I change the footer text (e.g. 'Thank you for your purchase!')? Two options: 1. **Easiest** — set it once for every receipt at **WP Admin > POS > Settings > Stores > Store details > Receipt footer / personal note**. Bundled templates pick it up automatically; if no footer is set, they fall back to a friendly default like *"Thank you for your purchase!"*. 2. **In a single template** — edit the template and replace the footer text directly. Look for `{{store.personal_notes}}` or the literal thank-you line. How do I add a tagline or slogan under the store name? Edit the template and add a line under `{{store.name}}`: ```
Family-owned since 1987
``` In a thermal template: ``` Family-owned since 1987 ``` How do I hide prices (for a gift receipt)? Click **Use Template** on the **Gift Receipt** card in the gallery — it hides every price and total while still showing items, SKU, attributes, and the gift message. No editing required. If you'd rather build your own price-free receipt, copy any template and delete the `{{...total...}}`, `{{...price...}}` and `{{#totals}}...{{/totals}}` blocks. How do I change the barcode to a QR code? Find the `` element in your template and change the `type` attribute: ``` {{order.number}} {{order.number}} https://example.com/returns?order={{order.number}} ``` The same `` syntax works in both HTML and thermal templates. Other supported types include `ean13`, `ean8`, `upca`, `pdf417`, and [everything bwip-js supports](https://github.com/metafloor/bwip-js/wiki/Supported-Barcode-Types). How do I send a different template to a specific printer? In the POS app, go to **POS > Settings > Printing**, then look under **Receipt templates**. You'll see each of your active templates with a printer dropdown next to it. Pick the printer you want, or leave it as **Auto**. * **Auto** matches templates to printers automatically — thermal templates go to thermal printers, HTML templates go to the system print dialog. * A **specific printer** overrides Auto and always sends that template there. * At print time, the cashier can override either of the above with the printer dropdown on the receipt screen. Routing is stored per-device, so each iPad or computer can have its own setup. My receipt still shows the old version after I edit it Click the WordPress **Update** button on the template edit screen. The editor doesn't auto-save — your changes only persist when you Update. For **Legacy PHP templates**, the preview in the editor shows the *last saved* version, not what you're typing. Save first, then refresh the preview. The preview is blank or shows 'No POS orders found' This only happens with **Legacy PHP templates**, which need a real order to preview against. Process a single POS order — even a $0 test sale — and the preview will start working. Logicless (HTML) and thermal templates always have sample data to fall back on, so they preview fine even on a brand-new store. I made a mess — how do I start over? Three safety nets: 1. The editor has **Undo** (Ctrl/Cmd + Z) for in-session changes. 2. Every save creates a WordPress **revision** — open **Revisions** on the edit screen to compare and restore any prior version. 3. If you started from a gallery template, click **Delete** on your copy in *Your Templates*, then click **Use Template** on the same gallery card again. You get a fresh, untouched copy. ## When to ask for help[​](#when-to-ask-for-help "Direct link to When to ask for help") * The template editor won't load, or saves don't stick. * The receipt prints fine on one device but not another. * You need a fiscal/legal layout for a specific country (Italy, Brazil, Spain, etc.) — these are usually handled by [WCPOS Pro](/getting-started/pro-license.md) or a country-specific integration. * You're trying to do something custom and AI can't quite get it right. Open a [support ticket](https://wcpos.com/support) and paste the template you're working with — that gives us everything we need to help. --- # HTML Templates HTML templates use a logicless Mustache-style syntax with `{{variable}}` placeholders. They render client-side in the POS app, which means they **work offline** — no server connection needed to display or print a receipt. This is the recommended engine for most users. ## Syntax[​](#syntax "Direct link to Syntax") ### Variables[​](#variables "Direct link to Variables") Insert data using double curly braces: ```

{{store.name}}

Order #{{order.number}}

Total: {{totals.total_display}}

``` Use `_display` variants for pre-formatted currency values (e.g., `$12.50` instead of `12.5`). See the [Receipt Data Reference](/receipts/receipt-data.md) for all available fields. ### Sections (Loops and Conditionals)[​](#sections-loops-and-conditionals "Direct link to Sections (Loops and Conditionals)") Use `{{#section}}...{{/section}}` to loop over arrays or conditionally show content: ``` {{#lines}}
{{name}} × {{qty}} {{line_total_display}}
{{/lines}} ``` ### Inverted Sections[​](#inverted-sections "Direct link to Inverted Sections") Use `{{^section}}...{{/section}}` to show content when a value is empty or false: ``` {{#customer.id}}

Customer: {{customer.name}}

{{/customer.id}} {{^customer.id}}

Guest checkout

{{/customer.id}} ``` ### Localised Labels[​](#localised-labels "Direct link to Localised Labels") Use `{{i18n.key}}` for translatable labels that adapt to the store's language: ``` {{i18n.subtotal}} {{totals.subtotal_display}} ``` ## Common Patterns[​](#common-patterns "Direct link to Common Patterns") ### Store Header[​](#store-header "Direct link to Store Header") The `store.address_lines` array is pre-formatted for receipts — loop it instead of stitching individual address fields together. ```
{{#store.logo}}{{store.name}}{{/store.logo}}

{{store.name}}

{{#store.address_lines}}
{{.}}
{{/store.address_lines}} {{#store.phone}}
{{store.phone}}
{{/store.phone}} {{#store.tax_ids}}
{{#label}}{{label}} {{/label}}{{value}}
{{/store.tax_ids}}
``` ### Line Items with Discounts[​](#line-items-with-discounts "Direct link to Line Items with Discounts") A line item's `discounts` field is the discount amount as a positive number, or `0` when there's no discount. Mustache treats `0` as falsy, so `{{#discounts}}...{{/discounts}}` is the right guard. ``` {{#lines}}
{{name}} × {{qty}}
{{#discounts}}
{{unit_subtotal_display}} {{unit_price_display}}
{{/discounts}}
{{line_total_display}}
{{/lines}} ``` ### Tax Summary[​](#tax-summary "Direct link to Tax Summary") ``` {{#tax_summary}}
{{label}} ({{rate}}%) {{tax_amount_display}}
{{/tax_summary}} ``` ### Payment Details[​](#payment-details "Direct link to Payment Details") ``` {{#payments}}
{{method_title}} {{amount_display}}
{{#tendered}}
{{i18n.tendered}}{{tendered_display}}
{{i18n.change}}{{change_display}}
{{/tendered}} {{/payments}} ``` ### Barcodes and QR Codes[​](#barcodes-and-qr-codes "Direct link to Barcodes and QR Codes") Use the `` element — the same syntax as [thermal templates](/receipts/thermal-templates.md). The value goes inside the element; the symbology is set on the `type` attribute. The renderer replaces each element with an inline SVG. ``` {{order.number}} {{order.payment_url}} {{order.number}} ``` The `type` attribute must be set **literally** in the template — it can't come from a placeholder. A `type` of `qr` or `qrcode` renders as a QR code in both HTML and thermal templates. If the selected barcode type can't encode the value (for example non-numeric or wrong-length EAN-13 data), the preview shows a `Barcode error` or `QR code error` block with the original value, so you can fix the value or switch to a compatible type. All [bwip-js symbologies](https://github.com/metafloor/bwip-js/wiki/Supported-Barcode-Types) are supported — `code128`, `qrcode`, `ean13`, `ean8`, `upca`, `pdf417`, `datamatrix`, and many more. ## Styling[​](#styling "Direct link to Styling") Logicless templates are sanitised through WordPress's `wp_kses_post` before rendering, which **strips `