# Square POS

Source: https://developers.swell.is/app-guides/square-pos

The Square POS app connects a shop that sells with Square Point of Sale to your Swell store, so both sell from one stock and keep one order history. When something sells, arrives or is recounted on either side, the other side has it, usually within a minute. Each sale completed in Square becomes a paid order in Swell, with the lines, discounts, taxes and total of its receipt.

Items are linked by SKU, and you start each pair and say which side has the right quantity. After that, only changes travel between Square and Swell, never totals, so a sale at the till and an online order at the same moment both count. In Square the app only adjusts stock: it doesn't change your catalog, orders or customers there. It connects with an access token from your own Square developer application.

## How it works

| When | What the app does |
| --- | --- |
| You choose Match products | Lists each Square item with the Swell product or variant that has the same SKU under Products > Square stock, with both quantities. Nothing moves yet. |
| You start an item | Gives the other side the starting quantity of the side you chose, as one stock adjustment. From then on the item is in sync. |
| Stock of a started item changes in Square | Adds the change to the product's stock in Swell, as a stock history entry marked Square POS, such as Square POS: 2 sold. |
| Stock of a started item changes in Swell | Adds the change to the item's stock in Square: an online order as sold, a canceled order or received stock as received, damaged or missing stock as lost. |
| A sale is completed in Square | Imports it as a paid Swell order, if Import completed Square sales as orders is on. |
| A payment of an imported sale is refunded in Square | Records the refund on the order. |
| Every five minutes | Compares the stock of all started items and looks for new Square sales, also when Square sent no notice. |
| An item can't be synced, or a sale can't be imported | Lists it under Needs attention with the reason, and e-mails the store's administrators. |

## Before you begin

- A Square account with at least one location.
- The same SKU on each product in Square and in Swell. Items are linked by SKU only. For products with variants in Swell, the SKUs go on the variants.
- Stock tracking turned on for the items in Square, at the location you share, and for the products in Swell.
- An application in the Square Developer Console, which only holds the access token. The token gives access to your whole Square account, so treat it like a password.
- To try the app first, the application's sandbox access token for your Swell test environment.

## Set up

Install Square POS from the Swell App Store, and set it up in your test environment before the live one.

**1. Get an access token**

In the Square Developer Console, create an application with any name. Open its **Credentials** page, switch to **Production**, and copy the **access token**. For your Swell test environment, copy the **Sandbox** access token instead.

**2. Connect Square**

In Swell, go to **Apps > Square POS > Settings**. Paste the token into **Square access token**, set **Square environment** to **Production**, or **Sandbox (test data)** for a sandbox token, and click **Save settings**. Then click **Test connection**. It checks the token, fills in **Connected account** with your Square business name, lists your locations in its message, registers the notices Square sends to your store when stock or payments change, and adds the **Square POS** payment method that imported sales are recorded with.

**3. Turn on the stock sync**

Under **Inventory**, turn on **Keep the stock of linked items in sync**. Leave **Square location (name)** empty to share the stock of your main Square location, or enter another location's name. If your store keeps stock by location, enter the Swell location in **Swell stock location (name)**. Click **Save settings**, and after setting or changing **Swell stock location (name)**, click **Test connection** again.

**4. Match and start your items**

Choose **Actions > Match products**, then **Match**. Then go to **Products > Square stock**. Items with a matching SKU are listed on the **Ready to start** tab with their quantity in Swell and in Square, and the others on **Not linked** with the reason.

Select the items to share, choose **Start syncing**, and choose which side has the right quantities: **Square: Swell takes Square's quantities** or **Swell: Square takes Swell's quantities**. Then click **Start**. Nothing moves for an item until it's started.

**5. Turn on the sales import**

Under **Sales**, turn on **Import completed Square sales as orders**, and click **Save settings**. Sales completed from then on are imported. To import from some locations only, enter their names in **Square locations (names, separated by commas)**. To import earlier sales, choose **Actions > Import past sales**, pick the date in **Import sales since**, and click **Import**.

**6. Test with a sale**

Sell a started item at the till, or in the Square sandbox. Within a minute, its stock in Swell goes down, with a stock history entry marked Square POS, and the sale appears under **Orders > Square sales** and as an order numbered `SQ-` and the receipt number. Then place an online order for a started item, and check that its stock goes down in Square.

**7. Go live**

Settings are saved separately for each environment. In the live environment, repeat steps 2 to 5 with your production access token.

Don't connect your test environment to your production Square account, or to the same location as your live environment: stock changes from test orders would reach your shop.

## Using Square POS

### Linking items

**Match products** pairs each Square item variation with the Swell product or variant that has the same SKU. An item is linked only when exactly one Square variation and exactly one Swell product or variant have the SKU. Matching changes nothing in Square, moves no stock, and leaves items that are already in sync as they are. Run it again whenever you add products or SKUs. Square variations without a SKU, or not available at the Square location under **Inventory**, aren't listed.

Items that can't be linked are listed on the **Not linked** tab with the reason:

| Reason | What to do |
| --- | --- |
| No Swell product or variant has the SKU | Give the Swell product or variant the SKU of the Square item, then match again. |
| More than one Square variation, or more than one Swell product or variant, has the SKU | Give each its own SKU. |
| The Swell product or variant is linked to another Square item | Stop syncing the other item first, or give this one its own SKU. |
| The Swell product has variants and the SKU is on the product | Give each variant its own SKU. Stock is kept on the variants. |
| Square doesn't track stock for the item at the location | Turn on stock tracking in Square, then match again. |
| The Swell product doesn't track stock | Turn on stock tracking for the product, then match again. |
| Square sells the item by weight or measure | Only whole quantities can be shared, so the item can't be linked. |

### Starting and stopping items

Starting an item is the one time a side wins. The side you choose keeps its quantity, and the other side receives the difference as one stock adjustment, shown in Swell's stock history as `Square POS: starting stock taken from Square`. An item that Square has never counted can be started from Swell's quantity.

To start one item, open it and choose **Actions > Start syncing**. To stop sharing, select items and choose **Stop syncing**, then **Stop**. Nothing changes on either side when you stop: each keeps the quantity it has. To share the stock again, start the item again and choose a side.

### How stock stays in sync

After an item is started, the app remembers the quantity both sides had after the last sync. What Swell gained or lost since then is added to Square, and what Square gained or lost is added to Swell. Neither side's total replaces the other's, so a sale at the till and an online order for the same item at the same moment both come off the stock.

| Happens | Arrives as |
| --- | --- |
| In Square: a sale, a delivery, a recount, a loss or a restocked return | An entry in the product's stock history in Swell, marked Square POS, with what happened when Square says so, such as Square POS: 2 sold. |
| In Swell: an online order | Stock sold, in Square. |
| In Swell: a canceled order, a restocked return or received stock | Stock received, in Square. |
| In Swell: stock marked damaged or missing | Stock lost, in Square. |

- Square announces a change within seconds, and the sync that follows takes a few seconds more. Every five minutes the app also compares all started items, so a lost notice costs minutes, not stock.
- When the last unit sells on both sides at once, both show −1. The item is listed under **Needs attention** as oversold until its stock is back to zero or more.
- When an item can no longer be synced, for example because its product was deleted or Square refuses the change, it stops and is listed under **Needs attention** with the reason. The other items go on. Correct the cause and start the item again.
- Changing **Square location (name)** or **Swell stock location (name)** stops the started items, because another location holds other quantities. Match products again and start them anew. A sync that's under way when you change them, or turn off **Keep the stock of linked items in sync**, stops after the items it's working on, and the next sync uses the new settings.

### Till sales as orders

With **Import completed Square sales as orders** on, each sale completed at the chosen Square locations becomes one Swell order:

- The lines of the receipt, with name, variation, quantity and price, the discounts and taxes Square charged, and tips, service charges, card surcharges and rounding up as lines of their own. Rounding down is a discount. The order total is what the customer paid. A sale whose lines don't add up to Square's total isn't imported: it's listed with the reason.
- Payments with the method **Square POS**, so the order shows as paid. Nothing is charged in Swell. A sale paid by card and cash gets one payment for each when they add up to the total, and one payment of the total otherwise.
- The number `SQ-` followed by Square's receipt number, or by the start of the Square order ID when there's no receipt number, so till sales stand out and don't use up your store's own order numbers. The order is dated when the sale was completed.
- The customer's Swell account when the sale has a Square customer whose e-mail address matches a Swell account. All other sales go to one account, **Walk-in customer (Square POS)**. The app never creates customers from Square.
- Comments that say where it was sold and how it was paid, and a **Square POS** tab on the order with the receipt number, the location, how it was paid, what was refunded, the Square order ID and a link to the receipt.

Imported orders need no fulfillment, send no e-mail to the customer or your staff, and take no stock: their lines carry names and amounts, not products, and the stock sync passes on what Square counted. So Swell's sales reports by product don't include till sales. Other apps and webhooks aren't told about imported orders unless **Let other apps and webhooks react to imported orders** is on.

Exchanges, with a sale and returned items on one receipt, aren't imported. Neither are sales an online checkout took through Square's payment API, because that checkout keeps its own orders; in **Sandbox** they're imported, because the sandbox has no till. Both are listed on the **Skipped** tab with the reason. A sale usually arrives within half a minute of its payment.

### Refunds

A refund made in Square is recorded on its order as a refund of the order's Square POS payment, so the order shows as partly refunded or refunded. A refund is recorded as soon as Square has it, also while Square still shows it as pending. Refunds of sales that weren't imported are left out. Stock follows Square's count when the goods are restocked there. If Swell refuses a refund, the sale is listed under **Needs attention** with the reason, and your administrators get an e-mail. Choose **Retry** after correcting the cause.

### Importing past sales

Sales completed before the import was turned on stay out, also when they're refunded later. So do the sales made while it was turned off: turning it on again starts the import anew from that moment. To import them, choose **Actions > Import past sales** in the app settings, pick the date in **Import sales since**, and click **Import**. A long period is imported in the background a part at a time, with the stock sync going on in between, so its orders arrive over several runs. A sale that was imported before is never imported twice. **Import past sales** works only while **Import completed Square sales as orders** is on.

### Needs attention and retries

Items that stopped are listed under **Products > Square stock > Needs attention**, and sales that couldn't be imported under **Orders > Square sales > Needs attention**, each with the reason. Correct the cause first. Then:

- To start an item again, select it and choose **Start syncing**.
- To retry sales, select them and choose **Retry**, then **Retry**, or open one and choose **Actions > Retry**. A retry also reads the sale's refunds again. A sale that has its order isn't imported twice. Retries work only while **Import completed Square sales as orders** is on: a sale retried while it's off shows as **In progress**, and can't be marked as resolved, until the import is turned on again.
- To retry every sale under **Needs attention**, choose **Actions > Retry failed sales** in the app settings.
- To compare all started items and look for new sales now, choose **Actions > Sync now** in the app settings.
- To stop a sale from being imported, for example after you recorded it by hand, open it and choose **Actions > Mark as resolved**, then **Mark as resolved**.

The actions run in the background, and the lists show their result a few seconds later. The runs are listed under **Apps > Square POS > Workflows**.

### E-mails to your administrators

The store's administrators get one e-mail per incident, not one per item or sale, and no other unless it comes back after a day without it. The subject starts with `Action needed:`, says what happened and ends with your store's name. Each e-mail says what to do and links to the app. The e-mail is the notification **Square POS needs attention**, which you can edit or turn off under **Settings > Notifications**.

| Subject after Action needed: | Sent when |
| --- | --- |
| Square POS is not syncing with … | Square refuses the access token, a location named in the settings doesn't exist or hasn't been checked yet, or the sales import has no start time yet. |
| Square's notices to … have stopped | Square turned off its notices to your store, or they were never registered. The app checks once an hour. |
| stock of … is no longer shared with Square for some items | An item stopped syncing. |
| a Square sale could not be imported into … | A sale is listed under Needs attention. |

### In the dashboard

| Where | What it's for |
| --- | --- |
| Apps > Square POS > Settings | The access token, Test connection, and the inventory and sales settings. |
| Apps > Square POS > Settings, Actions menu | Sync now, Match products, Import past sales and Retry failed sales. |
| Apps > Square POS > Workflows | The background runs of the app's actions. |
| Products > Square stock | The Square items and their Swell match, with the Needs attention, In sync, Ready to start and Not linked tabs, Match products and Open Square, and Start syncing and Stop syncing for selected items. |
| An item | Its SKU, status, both quantities and last change, Open Square, and Start syncing and Stop syncing in its Actions menu. |
| Orders > Square sales | Every imported, failed and skipped sale, with the Needs attention, Imported, Refunded and Skipped tabs, Open Square, and Retry for selected sales. |
| A sale | Its receipt, status, total, refunds and problem, View receipt, and Retry and Mark as resolved in its Actions menu. |
| An order's Square POS tab | The receipt number, location, how it was paid, what was refunded, the Square order ID and the receipt link. |
| The order list, Square POS tab | The orders imported from Square. |
| Settings > Notifications | The e-mail Square POS needs attention. |

## Settings

Settings are in **Apps > Square POS > Settings** and are saved separately for each environment. They're in three sections, **Connection**, **Inventory** and **Sales**.

| Setting | Description | Default |
| --- | --- | --- |
| Square access token | Connection. The access token of your Square application. Masked on the settings page. | None |
| Square environment | Connection. Production, or Sandbox (test data). It must match the token: a sandbox token works only with Sandbox. | Production |
| Connected account | Connection. Read-only. The Square business name, with (sandbox) for a sandbox account, filled in by Test connection. | None |
| Keep the stock of linked items in sync | Inventory. While off, no stock moves in either direction. | Off |
| Square location (name) | Inventory. The one Square location whose stock is shared with the store. Empty: the account's main location. | None |
| Swell stock location (name) | Inventory. Only for stores that keep stock by location: the Swell location paired with the Square one. Empty: the store's stock as a whole. | None |
| Import completed Square sales as orders | Sales. Turning it on starts the import from the moment the settings are saved, also when it's turned off and on again: sales made while it was off aren't imported. Import past sales and Retry work only while it's on. | Off |
| Square locations (names, separated by commas) | Sales. The locations whose sales are imported. Empty: all active locations. | None |
| Let other apps and webhooks react to imported orders | Sales. Off: imported orders raise no events, so other apps and webhooks aren't told about them. Customers get no e-mail either way. | Off |

## Limitations

- The app connects with an access token from your own Square application, not Square's OAuth sign-in. The token has access to your whole Square account and is stored in the store's settings.
- Products aren't created or changed on either side. Items are linked by the SKUs you keep.
- Stock is shared with one Square location. Sales can be imported from any number of locations.
- Items sold by weight or measure aren't linked. On an imported order, such a line is one unit at the amount Square charged.
- In a sale with taxes included in the price and taxes added on top, only the added taxes are listed on the order. The included ones stay in the prices, and the total is Square's.
- Sales are imported in the currency of their Square location. If your store has no prices of its own in that currency, the sale isn't imported and is listed under **Needs attention**, because Swell would record the order in another currency at the receipt's amounts.
- Refunds are recorded as amounts. Returns by item and exchanges aren't mirrored on the order, and a partly refunded order shows the refunded amount as a balance.
- A card refund that Square later reports as failed stays recorded on the order. Correct it by hand.
- Imported orders aren't linked to products, so they don't appear in sales reports by product.
- Square gift cards are shown only as the way a sale was paid, and loyalty rewards arrive as discounts.
- Connecting the test and live environments of a store to the same Square location makes both share its stock.
- When the last unit sells on both sides at once, both sides go below zero. No sync can prevent it.

## Troubleshooting

Problems are shown on the item or sale, and under **Needs attention** in **Products > Square stock** and **Orders > Square sales**. The app also logs errors. In the Swell dashboard, the logs are under **Developer > Console > Logs**.

### Test connection fails

`Enter the Square access token, save the settings, then test again` means no token is saved. If Square doesn't accept the token, it was replaced in Square, or **Square environment** doesn't match it: a sandbox token works only with **Sandbox (test data)**. Copy the token again from your application's **Credentials** page, save, and test again.

### E-mail "Square POS is not syncing with …"

Square refused the access token, or a location named in the settings doesn't exist. Correct it in the settings and click **Test connection**. Nothing is lost: once the connection works, the changes on each side since the last sync are passed to the other, and the sales made in the meantime are imported. `The Swell stock location "…" has not been checked yet. Press Test connection.` means **Swell stock location (name)** was set or changed: click **Test connection**.

`The sales import has no start time yet. Open the app's settings and save them once.` means the settings were last saved before the app recorded when the import was turned on, and no sales are imported until they're saved. Click **Save settings** in **Apps > Square POS > Settings**. The import starts from that save, so import the sales completed in the meantime with **Actions > Import past sales**.

### E-mail "Square's notices to … have stopped"

Square turns off its notices when they fail for a long time, or they were never registered. Click **Test connection** to register or turn them on again. In the meantime, changes are found every five minutes.

### An item isn't listed, or is under Not linked

Square variations without a SKU, or not available at the Square location under **Inventory**, aren't listed. For an item on the **Not linked** tab, the reason says what to fix, such as a missing or shared SKU or stock tracking that's off. Fix it, then choose **Match products** again.

### An item is under Needs attention

The item stopped syncing, or it's oversold. Its note says what stopped it. Correct the cause and start the item again. An oversold item leaves **Needs attention** once its stock is back to zero or more.

### Stock differs between Square and Swell for a started item

It shouldn't for longer than five minutes. Choose **Actions > Sync now** in the app settings. If the item is under **Needs attention**, see above.

### "The lines of the Square order add up to …, but its total is …"

The sale isn't imported, so that no order differs from its receipt. Record it in Swell by hand if you need it, and choose **Mark as resolved**.

### "Order … has a total of … in Swell, but the Square receipt says …"

The order was created but its total differs from the receipt. Correct the order by hand, then mark the sale as resolved.

### "Swell records this sale's order in …, at the amounts of the … receipt"

Your store has no prices of its own in the currency of the Square sale, so Swell would keep the order in another currency at the receipt's amounts. The sale isn't imported. Record it in Swell by hand if you need it, and choose **Mark as resolved**. When the message names an order, an earlier attempt created it: correct or delete that order by hand first.

### A sale is under Needs attention

The problem is on the sale. Choose **Retry** after correcting the cause, or **Mark as resolved** after recording the sale by hand. If Swell has no **Square POS** payment method, because it was removed under **Settings > Payments**, click **Test connection**, which adds it again, then retry.

### A sale is under Skipped

Exchanges and sales taken by an online checkout through Square's payment API aren't imported. The reason is on the sale.

### Sales aren't imported

Check that **Import completed Square sales as orders** is on, and that **Square locations (names, separated by commas)** is empty or names the location. Sales completed before the import was last turned on, including those made while it was off, are imported only with **Import past sales**.

## Uninstalling

Uninstalling the app stops the stock sync and the sales import, and removes the app's settings, its functions, the **Square stock** and **Square sales** lists, the **Square POS** tabs on orders, and the notification. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.

The orders imported from Square, their payments and refunds, the walk-in account, the **Square POS** payment method and the stock history entries stay in Swell. Your Square catalog, stock and sales stay as they are. After uninstalling, delete the app's subscription under **Webhooks** in your application in the Square Developer Console, named `Swell` and your store ID, with `(test)` for the test environment, or Square keeps sending notices until it gives up.

## For developers

| Function | Runs on | What it does |
| --- | --- | --- |
| square-events | A public route, called by Square's notices | Checks the notice's signature, marks the items whose count changed or asks for a sales search, and starts a sync. |
| stock-changed | product.stock_adjusted | Marks the product's item and starts a sync. |
| sweep | Cron, every 5 minutes | Starts a sync that compares every started item and looks for new sales. Once an hour, checks that Square's notices are still on. |
| sync | A workflow, started by the functions above and by the dashboard actions | The only place where stock is written and sales are imported. Runs Match products, Start syncing, Stop syncing, Import past sales, Retry and Sync now. |
| test-connection | The Test connection button | Checks the token, lists the locations, registers or updates Square's webhook subscription, and adds the Square POS payment method. |
| resolve-sale | The Mark as resolved action | Marks a failed or skipped sale as resolved. |

The app's permissions are `write_products`, `write_orders`, `write_payments`, `write_accounts` and `write_settings`: stock entries, imported orders with their payments and refunds, the walk-in account and the match by e-mail, and the stock locations and the Square POS payment method.

The app collections are `apps/squarepos/items`, one record per linked Square variation with its Swell product or variant, status (`unlinked`, `ready`, `active` or `error`), both quantities and the step in progress; `apps/squarepos/sales`, one record per Square sale with its status, receipt, total, refunds and order; `apps/squarepos/alerts`; and `apps/squarepos/state`, which holds the webhook subscription, the time the sales import was turned on, and the searches for new and past sales with their time range, locations and Square's cursor. Imported orders get `$app.squarepos` fields: `square_order_id`, `receipt_number`, `receipt_url`, `location_name`, `tender` and `refunded`.

The time the sales import was turned on is computed by the settings save that turns it on, in the hidden field `sales.enabled_at`: later saves keep it, and turning the import off clears it. A search of Square's orders is saved as it goes, so the next step or run goes on where it stopped. Only the workflow, while it holds the claim, starts or drops a search.

The app calls the Square API at `https://connect.squareup.com/v2`, or `connect.squareupsandbox.com` for Sandbox, with API version `2026-09-16`: `GET /merchants/me` and `/locations`; `GET /catalog/list` and `POST /catalog/batch-retrieve`; `POST /inventory/counts/batch-retrieve`, `/inventory/changes/batch-retrieve` and `/inventory/changes/batch-create`; `POST /orders/search`, for ten locations at a time, and `GET /orders/{id}`, `/payments/{id}`, `/refunds/{id}` and `/customers/{id}`; and the `/webhooks/subscriptions` endpoints. Square's notices go to `/functions/squarepos/square-events` on your store, with the store's public key in the address, and are checked against the subscription's signature key.

A notice only marks what to look at: the sync compares quantities, so repeated or out-of-order notices do no harm. Each step is saved on the item before it's taken, and a step cut short is repeated exactly: the app asks Square whether the change is there before it sends it again, and a stock entry posted twice under one ID is one entry. A step records the Swell stock location it was decided for, and one cut short before that location changed stops the item instead. A run reads the stock settings again before each batch and leaves the stock alone once they've changed. Only one sync runs at a time; a claim that shows no sign of life for four minutes is taken over.

## Support

Swell builds and maintains the Square POS app. For help with the app, email support@swell.is. For questions about your Square account, contact Square support.
