Frappe Square Sync
ERPNext ↔ Square catalog/stock/sales/customer sync for Frappe (AGPL-3.0)
- Author: JamesonRGrieve
- Repository: https://github.com/JamesonRGrieve/frappe-square-sync
- GitHub stars: 0
- Forks: 0
- License: AGPL-3.0
- Category: Integrations
- Maintenance: Actively Maintained
Install Frappe Square Sync
bench get-app https://github.com/JamesonRGrieve/frappe-square-sync
Add the Frappe Gems badge to your README
Maintain Frappe Square Sync? Paste this into your README:
[](https://frappegems.com/gems/apps/JamesonRGrieve/frappe-square-sync)
About Frappe Square Sync
frappe-square-sync
Keeps ERPNext and Square in step for one Square merchant per Square Sync Settings, across every location that sells. ERPNext is the master for the catalog, prices and stock. Square counter sales, refunds, gift card activity and customers come back into ERPNext. ERPNext customers and webshop orders go out to Square, so the sync runs both ways.
> Not yet run against Square. Nothing in this app has run against the Square sandbox or a live > Square account. Every Square request and response the tests use is a recorded fixture, validated > against Square's published OpenAPI document (pinned by commit), and the engine is tested against a real > ERPNext test database. The go-live gate below has not been passed.
| Data | Direction | How |
|---|---|---|
| Catalog items, variants, images | ERPNext → Square | Batch catalog upsert. Templates become items, variants become variations, SKU = item code. |
| Prices | ERPNext → Square | From the sync's price list. A location with its own price list gets per-location price overrides. |
| Stock | ERPNext → Square | Absolute counts per location: actual − reserved in that location's warehouse, so Square can't oversell. |
| Counter sales | Square → ERPNext | A submitted Sales Invoice at the location's warehouse, with itemised discounts, one row per tax, service charges, tips and rounding. |
| Tenders | Square → ERPNext | One Payment Entry per tender, to its tender type's mode of payment and account. Square's processing fee is a deduction. |
| Returns, exchanges, refunds | Square → ERPNext | Credit notes with stock back (items Square wrote off leave again as a Material Issue), refund Payment Entries out of the original tender's account, and a Journal Entry settling an exchange. Refunds with no returned items become amount-only credit notes. |
| Voids, later tip adjustments | Square → ERPNext | A void cancels what was booked. A changed sale is cancelled and amended with its payments. |
| Gift cards | Square → ERPNext | Card sales credit the gift card liability, never revenue. The SQUARE_GIFT_CARD tender debits it. Any other activity that moves money is a Journal Entry against a clearing or breakage account. Each card is mirrored in a Square Gift Card register. |
| Loyalty | Square → ERPNext | Square Loyalty is the one points balance. Each loyalty event that moves points is a Loyalty Point Entry on an ERPNext Loyalty Program mirroring it; ERPNext neither earns nor redeems that program's points. Completed webshop orders earn their points in Square. |
| Customers | Both ways | Square customers become Customers with a contact and address. ERPNext customers are created and updated in Square; the echo links back through reference_id. |
| Webshop orders | ERPNext → Square | A webshop checkout paid through frappe-payment-square becomes a Square order at the webshop location, priced to the charged amount and paid by the card payment itself. |
Setup
One Square Sync Settings per merchant:
- Locations: each Square location that sells, with its warehouse, an optional price list and cost center.
- Tenders: each tender type's mode of payment and account. A sale paid with a tender type that has no
row is held back until one is added.
SQUARE_GIFT_CARDmust book to the gift card liability account. - Taxes: an account per Square tax (matched by catalog tax ID, then by name). Other taxes use the default tax account.
- Gift cards: the gift card item and the liability, clearing and breakage accounts.
- Loyalty: switch on "Mirror Square Loyalty" (the ERPNext Loyalty Program is created on the first run) and, if wanted, "Earn Points on Webshop Orders". The seller needs a Square Loyalty subscription.
- Sources Booked Elsewhere: Square order sources this app never books (see Policies).
- Rejected Phone Numbers: what to do with a customer phone Square refuses (see Policies).
The webhook URL is /api/method/square_sync.api.webhook?sync=, registered in Square exactly as
it appears in the settings, with the signature key stored there. Subscribe to order.*, payment.updated,
refund.*, gift_card.*, gift_card.activity.*, loyalty.event.created, customer.* and
inventory.count.updated.
Credentials are written by the deploy pipeline from OpenBao. Never enter them by hand or commit them.
How it stays exact
- Every Square object is tracked in a Square Sync Link, one per Square object and kind, enforced by a unique index. A webhook run and the scheduled run that race on one order can't both book it: the second one's transaction rolls back.
- Each location reads orders and refunds by
updated_at, and its cursor only moves past what booked cleanly. Anything that can't be booked exactly (an unlinked item, an unmapped tender, totals that don't match Square's, a card not yet captured) is held back, logged and retried. It is never approximated or skipped. - Triggers: doc events push catalog, stock and customer changes; Square webhooks enqueue the matching step; a 10-minute reconciliation catches anything missed.
Policies
These are settings, so each merchant can choose. The defaults never book anything twice and never lose data.
- Sources Booked Elsewhere (default
WooCommerceandWooCommerce Square). With WooCommerce Square's order sync on, WooCommerce's online orders also exist in Square. If another integration (for example the importer's WooCommerce source) already books them in ERPNext, booking them here too would count each sale twice. Orders from these sources are not booked. Each one is listed as askipped_orderSquare Sync Link. If nothing else books them, remove the source and replay from an earlier cursor. The exact source name WooCommerce Square's orders carry is unverified (Square sets it to the name of the app that created the order); confirm it in the sandbox. - Existing installs. The upgrade patch turns each sync's single location, warehouse and cursor into
its first Locations row. Its single mode of payment and deposit account become the row for every tender
type except
SQUARE_GIFT_CARD, so today's bookings carry on unchanged. Cash should then get its own account. Sales paid with a gift card are held back (not lost) until theSQUARE_GIFT_CARDrow and the gift card accounts are set up. Existing syncs also get the default Sources Booked Elsewhere. - Square-only discounts and taxes are booked as they are, per line and per rate on the invoice: the discount names and amounts on each line, and each tax as its own row. They are not created as ERPNext Pricing Rules or tax templates, because ERPNext is the catalog master and Square applied them already.
- Rejected Phone Numbers (default: push without the phone). Square takes 9 to 16 digits. A phone outside that either stays in ERPNext only while the customer goes to Square without it, or, with "Hold the customer back", keeps the customer out of Square until the number is fixed.
Unverified until the sandbox run
- Whether the refund id inside a return order equals the Refunds API's
PaymentRefundid. Either way it is booked once: a Refunds API refund on an itemised return is linked to the order's refund entry for the same tender and amount. - Whether a waste write-off carries the refund id or the order's
transaction_id(both are matched). - Whether a Square order with no fulfilment completes on its own once paid (webshop orders).
- Whether ListGiftCardActivities' default one-year window drops older card history.
- Whether EXPIRE_POINTS events report expired points as a positive count (taken as one, and subtracted).
- Whether a webshop order paid in Square reaches COMPLETED (it earns loyalty points only then).
Go-live gate
A Square sandbox round trip covering: catalog and per-location price push; a counter sale split across card, cash and gift card tenders; a return with stock back; an exchange; an amount-only refund; a void; a later tip adjustment; a gift card sold, redeemed and adjusted; loyalty points earned, rewarded and adjusted; customer push and import; a webshop order; and no oversell under concurrent sales. Plus the order source WooCommerce Square's orders carry.
Development
ruff format --check . && ruff check .
python3 -m tools.validate_fixtures # recorded exchanges against Square's OpenAPI document
python3 -m tools.gen_fixtures # regenerate the fixtures (then validate them)
bench --site run-tests --app square_sync
License: AGPL-3.0-or-later.
Related Integrations apps for Frappe & ERPNext
- Insights — Open Source Business Intelligence Tool
- Raven — Simple, open source team messaging platform
- Frappe Whatsapp — WhatsApp cloud integration for frappe
- Frappe Assistant Core — Infrastructure that connects LLMs to ERPNext. Frappe Assistant Core works with the Model Context Protocol (MCP) to expose ERPNext functionality to any compatible Language Model
- Biometric Attendance Sync Tool — A simple tool for syncing Biometric Attendance data with your ERPNext server
- Frappe React Sdk — React hooks for Frappe
- Frappe Js Sdk — TypeScript/JavaScript library for Frappe REST API
- Mcp — Frappe MCP allows Frappe apps to function as MCP servers