pos-integration
Connect your physical point-of-sale system to your online store for unified inventory, shared customer records, and omnichannel order management
What this skill does
# POS Integration
## Overview
Point-of-sale integration connects your physical retail operations with your online store, enabling unified inventory visibility, centralized order management, and consistent customer profiles across channels. When a customer buys in-store, the online store must reflect the updated inventory immediately; when they return an online order in-store, the refund must flow back to the payment gateway. This skill covers connecting Square and Shopify POS to your commerce platform, synchronizing inventory in real time, and handling cross-channel returns.
## When to Use This Skill
- When opening a physical retail location alongside an existing online store
- When inventory discrepancies between in-store and online are causing oversells
- When customers expect to return online purchases in-store (omnichannel returns)
- When franchised or multi-location retail needs unified inventory and reporting
- When building a custom kiosk or tablet-based POS application
## Core Instructions
### Step 1: Determine your platform and POS integration path
| Platform | Easiest POS Integration | What Gets Unified |
|----------|------------------------|------------------|
| **Shopify** | **Shopify POS** (built-in, $89/month for Pro) — designed to work with Shopify's online store natively | Inventory syncs instantly between POS and online store; orders appear in unified admin; customer profiles and loyalty points unified |
| **WooCommerce** | **Square** + WooCommerce Square plugin (free) | Inventory syncs bidirectionally; Square POS sales update WooCommerce stock; orders can be imported into WooCommerce |
| **BigCommerce** | **Square** + BigCommerce Square integration | Same as WooCommerce but configured in BigCommerce's channel settings; BigCommerce also supports Stripe Terminal directly |
| **Custom / Headless** | **Square API** or **Stripe Terminal** | Full control — sync inventory via webhooks, import POS orders via API, build unified order dashboard |
### Step 2: Platform-specific POS setup
---
#### Shopify + Shopify POS
Shopify POS is the most seamless option for Shopify stores since inventory is managed in a single system:
1. **Subscribe to Shopify POS Pro** ($89/month or included in Shopify Plus):
- Go to **Point of Sale → Devices** in your Shopify admin
- Install the Shopify POS app on your iPad or iPhone
- Connect a card reader (Shopify provides its own Tap & Chip reader)
2. **Set up locations for each store:**
- Go to **Settings → Locations** and click **Add location** for each physical store
- Assign inventory quantities per location — Shopify tracks stock at each location separately
3. **Inventory automatically stays in sync:**
- A sale in the POS app immediately decrements inventory for that location
- The online store can be configured to sell from multiple locations (go to **Settings → Shipping and delivery → Local pickup** to configure)
4. **Configure click-and-collect (Buy Online, Pick Up In Store):**
- Go to **Settings → Shipping and delivery → Local pickup** and enable it for each location
- Customers select their pickup location at checkout; the order appears in that store's POS app under **Pickups**
---
#### WooCommerce + Square
**Connect Square to WooCommerce:**
1. Install the **WooCommerce Square** plugin (free, developed by Square) from wordpress.org
2. Go to **WooCommerce → Settings → Integrations → Square** and click **Connect with Square**
3. Log in to your Square account and select your Square business location
4. In the Square plugin settings, enable **Sync inventory** (bidirectional)
5. Run the initial sync: go to **WooCommerce → System Status → Tools → Sync Products with Square**
**How inventory sync works:**
- When you sell a product in your Square POS, WooCommerce stock decrements automatically (within minutes via webhook)
- When WooCommerce receives an online order, Square stock decrements
- Go to **WooCommerce → Square → Sync Log** to see sync history and troubleshoot discrepancies
**Handle in-store returns of online orders:**
- Returns initiated in WooCommerce admin automatically sync to Square if the original payment used Square
- For Stripe-paid online orders returned in-store: process the refund in Square and reconcile in WooCommerce manually, or build a custom refund endpoint (see Custom section below)
---
#### BigCommerce + Square
1. Go to **Channel Manager** in your BigCommerce admin and click **+ Create New Channel**
2. Select **Square** from the channel list
3. Authorize BigCommerce to connect to your Square account
4. Configure inventory sync settings — BigCommerce and Square will sync stock levels bidirectionally
5. Square POS orders can be imported into BigCommerce for unified reporting
---
#### Custom / Headless + Square API
**Initialize the Square client:**
```typescript
// lib/pos/square-client.ts
import { Client, Environment } from 'square';
export const squareClient = new Client({
accessToken: process.env.SQUARE_ACCESS_TOKEN!,
environment: process.env.NODE_ENV === 'production' ? Environment.Production : Environment.Sandbox,
});
export const { catalogApi, inventoryApi, ordersApi, paymentsApi, locationsApi } = squareClient;
```
**Handle Square inventory webhooks (in-store sale → update online store):**
```typescript
// POST /api/webhooks/square
import { createHmac } from 'node:crypto';
export async function POST(req: NextRequest) {
const rawBody = Buffer.from(await req.arrayBuffer());
const signature = req.headers.get('x-square-hmacsha256-signature') ?? '';
// Square HMAC includes the full notification URL in the signature
const notificationUrl = `${process.env.APP_URL}/api/webhooks/square`;
const expected = createHmac('sha256', process.env.SQUARE_WEBHOOK_SECRET!)
.update(notificationUrl + rawBody.toString('utf8'))
.digest('base64');
if (signature !== expected) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
}
const event = JSON.parse(rawBody.toString('utf8'));
if (event.type === 'inventory.count.updated') {
const counts = event.data.object.inventory_counts ?? [];
for (const count of counts) {
const variant = await db.variants.findBySquareCatalogId(count.catalog_object_id);
if (!variant) continue;
await db.inventory.updateLocationQuantity(variant.sku, count.location_id, parseInt(count.quantity));
const total = await db.inventory.getTotalAvailable(variant.sku);
await redis.setex(`inventory:${variant.productId}`, 3600, String(total));
}
}
return NextResponse.json({ accepted: true });
}
```
**Handle cross-channel returns (online order returned in-store):**
```typescript
// lib/pos/returns.ts
export async function processInStoreReturn(params: {
orderId: string;
lineItems: Array<{ lineItemId: string; quantity: number }>;
locationId: string;
}) {
const { orderId, lineItems, locationId } = params;
const order = await db.orders.findById(orderId);
if (!order) throw new Error(`Order ${orderId} not found`);
// Calculate refund amount
const refundAmount = lineItems.reduce((sum, item) => {
const line = order.lineItems.find(l => l.id === item.lineItemId)!;
return sum + (line.unitPriceCents * item.quantity);
}, 0);
// Issue refund via original payment gateway
if (order.paymentGateway === 'stripe') {
await stripe.refunds.create({
payment_intent: order.stripePaymentIntentId,
amount: refundAmount,
metadata: { orderId, locationId, channel: 'in_store_return' },
});
} else if (order.paymentGateway === 'square') {
await paymentsApi.createPaymentRefund({
idempotencyKey: `return_${orderId}_${Date.now()}`,
paymentId: order.squarePaymentId!,
amountMoney: { amount: BigInt(refundAmount), currency: 'USD' },
});
}
// Restock returned items at the return location
for (const item of lineItems) {
const line = order.lineItems.find(l => l.id === item.lineItemId)!Related in integrations-apis
product-information-management
IncludedCentralize product data in a PIM system like Akeneo or Salsify and syndicate enriched content to all your sales channels automatically
webhook-architecture
IncludedBuild a reliable event delivery system with automatic retries, HMAC signature verification, and dead-letter queues so no webhook is ever lost
email-service-integration
IncludedSend reliable transactional emails (order confirmations, shipping updates) via SendGrid, SES, or Postmark with templates and deliverability best practices
analytics-integration
IncludedImplement GA4, Meta Pixel, and server-side tagging with a proper data layer so you capture accurate conversion events for ad campaigns
erp-integration
IncludedSync orders, inventory, and customer data between your store and ERP systems like SAP, NetSuite, or Odoo using middleware and async queues
marketplace-connectors
IncludedList products on Amazon, eBay, and Walmart with two-way inventory sync, automated listing creation, and order import into your store