Skip to content

Square Integration Setup

Looking for guided setup? Start Emily in the backoffice for step-by-step guided setup.

For a merchant-facing overview, see the Square Integration feature doc.

Overview

Square is a merchant-scoped full POS integration that handles both order management and payment processing. Unlike other integrations, Square manages payments directly -- no separate payment provider is needed. Menu, locations, and inventory sync between Square and Upvendo, with the direction decided automatically per entity.

Integration Type: Full POS integration (merchant-scoped, not location-scoped) Sync Direction: Per-entity automatic (push / pull / skip) for locations, menu (categories, modifier groups, items, variant groups), and inventory Payment Handling: Square handles all payments -- kiosk (Square Terminal) and online (Square Web Payments SDK) Authentication: OAuth2 authorization code flow with a base64-encoded JSON state parameter (vendor_id + timestamp + random nonce) for CSRF protection

Menu Flexibility: You can either sync your existing menu from Square OR create items in Upvendo and push them to Square.

Key Benefits:

  • No Payment Profile needed -- Square handles kiosk payments (Square Terminal) and online payments (Square Web Payments SDK)
  • Locations are imported automatically with rich data (address, business hours, coordinates, timezone, language, currency, phone, email, social links)
  • Automatic per-entity sync for menu items, categories, modifier groups, variant groups, and inventory
  • Webhooks for location changes, catalog updates, inventory changes, device pairing, and payment confirmations

Purpose

The Square integration serves merchants who use Square as their POS system and want to:

  • Use Upvendo's kiosk and online ordering channels powered by Square payments
  • Keep their menu, locations, and inventory synchronized between Square and Upvendo
  • Process payments through Square Terminal (kiosk) or the Square Web Payments SDK (online)
  • Manage everything from a single back-office while keeping Square as the payment processor

Key Concepts

ConceptDescription
Merchant-ScopedUnlike location-scoped integrations, the Square integration covers the entire merchant account. All locations under the Square merchant are synced.
SquareIntegration RecordA specialized integration record (extends ThirdPartyIntegration, app/RawModels/SquareIntegration.php) storing OAuth credentials, merchant ID, sync status, logs, and settings. Provider is square.
External IDsUpvendo entities store their Square counterpart IDs in external_ids.square (and external_ids.square_item_id for the parent Square item). Square entity snapshots and sync metadata are stored in external_data.square.
Sync DirectionFor each entity, the system determines whether to push (Upvendo to Square), pull (Square to Upvendo), or skip, based on timestamps and a content hash.
Sync HashAn MD5 hash of the Square entity's JSON representation (after stripping server-managed fields like version, updated_at, and the present/absent_at_location arrays), stored on the Upvendo entity to detect changes in Square.
Last Synced AtTimestamp of the last reconcile with Square for that entity (bumped on both push and pull). Used with the sync hash to determine sync direction.
Daily Auto-SyncA configurable daily sync (locations, menu, inventory) driven by the InHouseAutoSyncCommand (in-house:auto-sync) scheduler.
Terminal CheckoutThe flow for processing kiosk payments through a paired Square Terminal device.

Prerequisites

Square integration is simpler than other POS systems because it handles payments:

1. Branding Profile Setup (Required)

  1. Go to Settings -> Brand (/settings/brand)
  2. Configure your store's branding (logo, colors, fonts)
  3. Square imports social links (Facebook, X/Twitter, Instagram) automatically, but does NOT provide colors, fonts, or logos

2. Billing Profile Setup (Optional)

  1. Go to Settings -> Billing (/settings/billing)
  2. Complete your billing information for Upvendo platform invoicing
  3. This is for Upvendo billing only -- NOT related to customer payments (Square handles those). The connect dialog warns if no default billing profile exists.

Note: Payment Profile is NOT required -- Square handles all customer payments directly.


Setup Steps

1. Connect Square Account (OAuth)

  1. Go to Square (/square) -> Settings tab
  2. Click Connect with Square
  3. You are redirected to Square's OAuth authorization page
  4. Log in to your Square account
  5. Authorize Upvendo to access your Square data
  6. After authorization you are redirected to /square/success and a full sync starts automatically (locations, menu, inventory)

OAuth Technical Details:

The authorization URL is generated by SquareIntegrationController::initiateOAuth and requests these scopes:

  • MERCHANT_PROFILE_READ, MERCHANT_PROFILE_WRITE -- Merchant and location info
  • ITEMS_READ, ITEMS_WRITE -- Catalog management (items, categories, modifiers, pricing)
  • ORDERS_READ, ORDERS_WRITE -- Order management
  • PAYMENTS_READ, PAYMENTS_WRITE -- Payment processing
  • INVENTORY_READ, INVENTORY_WRITE -- Stock level management
  • CUSTOMERS_READ, CUSTOMERS_WRITE -- Customer info for orders/payments
  • DEVICES_READ, DEVICE_CREDENTIAL_MANAGEMENT -- Terminal device management

The state parameter is a base64-encoded JSON payload with vendor_id, timestamp, and a random nonce for CSRF protection. The authorize URL also sets session=false.

Token exchange (GET /square-callback, route name square.callback):

  • The callback decodes state to recover the vendor_id, then SquareIntegrationService::handleSquareCallback exchanges the authorization code at POST https://connect.squareup.com/oauth2/token (or connect.squareupsandbox.com in sandbox)
  • The response is stored under the integration record's credentials: access_token, refresh_token, expires_at, refresh_token_expires_at, merchant_id (Square's merchant ID), plus token_type and short_lived
  • The merchant's provider_integrated is set to square
  • On success the user is redirected to {backoffice_url}/square/success; on failure to {backoffice_url}/square/error?message=...

2. Locations Imported Automatically

Once connected, the location sync runs in two phases (SquareLocationSync::syncLocations):

  • Phase 1: push existing Upvendo locations to Square (or pull, per the direction algorithm)
  • Phase 2: import any Square locations not yet linked to an Upvendo location

For each imported Square location, Upvendo:

  • Imports location data -- address (via SquareAddressConverter), business hours (via SquareBusinessHoursConverter), coordinates, timezone, language, currency, phone, email, description, status
  • Creates a branding profile per location (with defaults + social links from Square)
  • Links billing using the default billing profile's Stripe customer ID (if one exists)

After import, go to Settings -> Locations (/settings/locations) to:

  • Verify imported data is correct
  • Customize branding (logo, colors, fonts -- Square doesn't provide these)
  • Add delivery zones (if doing delivery)

3. Configure Sync Settings

SettingDescription
Daily Sync Time (sync_time)Time of day the automatic sync runs (menu, locations, inventory). Format: HH:00 or HH:30.
Auto-sync enabled (enable_auto_sync)Internal boolean that controls whether the daily auto-sync runs. Accepted by the update endpoint; the back-office UI surfaces only the sync time field.

The back-office Settings tab exposes the daily sync time. There are no per-data-type toggles (items/orders/inventory) and no sync-direction picker -- all sync features run together and direction is decided automatically. You can also trigger a manual full sync at any time from the Status tab.

4. Test the Integration

  1. Go to the Square page -> Status tab
  2. The page shows a connection status; use Sync Now to run a manual sync (the backend GET /square/test endpoint fetches merchant info to verify connectivity)
  3. For kiosk: pair a Square Terminal and process a test payment
  4. For online ordering: place a test order and verify the payment completes

Data Sync Details

Sync Direction Algorithm

For every entity (location, category, modifier group, item, variant group), determineSyncDirection() (in SquareSyncDirectionTrait) picks a direction:

  1. Get last_synced_at -- last reconcile timestamp (bumped on push and pull)
  2. Get last_sync_hash -- MD5 hash of the Square entity at last sync (server-managed fields stripped first)
  3. Compare Upvendo updated_at against last_synced_at to detect Upvendo changes
  4. Compare current Square hash against last_sync_hash to detect Square changes
Upvendo ChangedSquare ChangedWebhook ContextResult
NoNoAnySkip (no sync needed)
YesNoAnyPush Upvendo to Square
NoYesAnyPull Square to Upvendo
YesYesYes (webhook)Square wins (webhook just fired)
YesYesNo (manual)Most recent wins (compare updated_at vs last_synced_at)

First sync (no last_synced_at or no Square entity): defaults to pushing from Upvendo to Square.

Location Sync

Phase 1: Sync Upvendo locations to Square

  • For each Upvendo location, determine sync direction
  • Push to Square: create or update the Square location with name, address, timezone, business hours, phone, email, website, description, status, coordinates, social links
  • Pull from Square: update the Upvendo location with Square data

Phase 2: Import unsynced Square locations

  • Any Square locations not already linked to an Upvendo location are imported, creating Upvendo locations with branding profiles

Data mapped:

Square FieldUpvendo Field
namename (unique-name generation if conflict)
addressaddress (via SquareAddressConverter)
timezonetimezone
business_hoursbusiness_hours (via SquareBusinessHoursConverter)
phone_numbercontact_information.phone
business_emailcontact_information.email
language_codepreferred_language
coordinatespin_point_latitude, pin_point_longitude
facebook_urlbranding_profile.social_links.facebook
twitter_usernamebranding_profile.social_links.x
instagram_usernamebranding_profile.social_links.instagram
website_urlonline_ordering_url
descriptiondescription
statusstatus (push to Square only; not mapped back on pull)
currencycurrency (import/create only; not pushed back to Square)

Menu sync runs three entity types in order (SquareIntegrationService::syncMenus):

  1. Categories -- between Upvendo categories and Square catalog categories
  2. Modifier Groups -- between Upvendo modifier groups and Square modifier lists
  3. Items -- between Upvendo items and Square catalog items, including variant groups

Direction for each entity is decided by the sync direction algorithm above.

Incremental sync: When triggered by a specific entity change (via SyncSquareMenuJob), only the changed entity is synced:

  • category -> syncSingleCategory()
  • modifier_group -> syncSingleModifierGroup()
  • item -> syncSingleItem()
  • variant_group -> syncSingleVariantGroup()

Full sync: When triggered by a catalog webhook (catalog.*) or daily/manual full sync, all categories, modifier groups, and items are synced.

SyncSquareMenuJob configuration:

  • Max retries ($tries): 3
  • Backoff: 60 seconds between retries

Inventory Sync

Inventory sync is per item variation per location (SquareInventorySync):

Push (Upvendo to Square): Sends physical-count changes via the Square Inventory API (batchCreateChanges). Pull (Square to Upvendo): Reads counts via the Inventory API (batchGetCounts) and updates Upvendo. Conflict between sides is resolved by comparing Square's calculated_at against the Upvendo update timestamp.

Inventory sync runs as part of the full sync (daily auto-sync or manual). Webhook-triggered inventory syncs (SyncSquareInventoryJob) target a specific catalog object + location.

Propagation Across Locations

When a modifier group is pushed to Square, SquarePropagation::propagateUpvendoModifierGroupToAllLocations copies the source data to all other Upvendo modifier groups that share the same Square modifier list ID (external_ids.square) at different locations, keeping multi-location setups consistent. Items and variant groups have analogous propagation.

Not fully verified here: field-by-field round-trip fidelity of the external_data.square snapshot blobs, variant-group option-combination reconstruction, and the cross-location distribution helper internals were not exhaustively traced.


Webhook Events

Square sends webhooks to POST /webhook/square (full path /api/webhook/square), verified by the verify.square-webhook middleware (VerifySquareWebhook). The middleware checks the X-Square-HmacSha256-Signature header against config('square.webhook_signature_key') using Square's WebhooksHelper::verifySignature. The verified payload is dispatched to ProcessSquareWebhookJob (async, $tries=3, $backoff=30, $timeout=120), which calls SquareWebhookService::processWebhook.

Event Deduplication

Square may retry failed webhooks. The system deduplicates by caching processed event_id values for 24 hours (86400s).

Anti-Recursion Protection

When Upvendo pushes changes to Square, a cache timestamp is set. If a webhook arrives within the threshold of a push, it is skipped to prevent recursive update loops:

  • Location: 10 seconds
  • Catalog: 10 seconds
  • Inventory: 15 seconds

Event Types

Routing is by event-type prefix (SquareWebhookService::processWebhook):

Event PrefixHandlerAction
location.* (created/updated)handleLocationEvent()Dispatches SyncSquareLocationJob
catalog.* (e.g. catalog.version.updated)handleCatalogEvent()Dispatches SyncSquareMenuJob (full sync)
inventory.* (e.g. inventory.count.updated)handleInventoryEvent()Dispatches SyncSquareInventoryJob
device.code.* (acts only on device.code.paired)handleDeviceCodeEvent()Direct device update (no job)
payment.* (acts only on payment.updated)handlePaymentEvent()Direct processing (no job)
order.*handleOrderEvent()Log-only (no ingestion)

Device Code Pairing (device.code.paired)

When a Square Terminal is paired:

  1. The webhook payload provides device_code_id (data.id) and device_id
  2. The system finds the Upvendo device with a pending device code matching device_code_id (external_data.square.device_code.id with is_pending == true)
  3. Updates the device record under external_data.square.device_code: sets terminal_device_id, is_pending = false, is_connected = true, and paired_at

Payment Processing (payment.updated)

When a payment completes:

  1. Only payment.updated with status COMPLETED is processed
  2. The reference_id (format {merchant_id}:{order_no}, decoded by SquareReferenceId) identifies the tenant and transaction; the transaction is matched on the decoded order_no. (Legacy bare order_no references fall back to mapping location_id to an Upvendo location via external ID.)
  3. If tip changed, the transaction's tip and total are updated
  4. Online ordering payments: run OnlineOrderingOrchestrator::verifyPayment() under a 30-second database lock
  5. Kiosk payments: run PaymentCaptureService::capturePayment() under a 30-second database lock

Actions

ActionMethodEndpointDescription
Get StatusGET/back-office/square/statusReturns integration status, sync info, settings
Initiate OAuthPOST/back-office/square/oauthGenerates the Square OAuth authorization URL
Update Sync TimePOST/back-office/square/sync-timeSet the daily auto-sync time (HH:00/HH:30) and optional enable_auto_sync
DisablePOST/back-office/square/disableRevoke token, delete the integration, clear payment provider
Start SyncPOST/back-office/square/start-syncTrigger a manual full sync (dispatches SyncSquareIntegrationJob)
Test ConnectionGET/back-office/square/testTest API connectivity by fetching merchant info
OAuth CallbackGET/square-callbackHandles OAuth redirect from Square (guest route, name square.callback)
WebhookPOST/webhook/squareReceives Square webhooks (guest route, verify.square-webhook middleware)
Online PaymentPOST/online-ordering/payment/processProcesses an online-ordering Square payment (OnlineOrderingController::processSquarePayment)

The merchant-facing /square/* routes are under the /back-office API prefix and the admin-vendor-override middleware.


Fields

Status Response (SquareIntegrationService::getStatus)

FieldTypeDescription
is_connectedbooleanWhether the integration is active
providerstringsquare
vendor_idstringThe Upvendo merchant (tenant) this integration belongs to
is_sandboxbooleanWhether using the sandbox environment
merchant_idstringSquare merchant ID (from credentials.merchant_id)
access_token_expires_atstringWhen the access token expires
is_token_expiredbooleanWhether the token needs refresh
settingsobjectIntegration settings
sync_statusobjectCurrent sync status, logs, connection status
last_sync_atstringTimestamp of last successful sync
sync_timestringConfigured daily auto-sync time
enable_auto_syncbooleanWhether daily auto-sync is enabled
created_at / updated_atstringRecord timestamps

Sync Time Request (UpdateSyncTimeRequest)

FieldTypeRequiredValidation
sync_timestringYesMust match HH:00 or HH:30 (regex: `^([01]?[0-9]
enable_auto_syncbooleanNo (sometimes)boolean

Payment Flow

Kiosk Payments (Square Terminal)

Customer Order -> Upvendo Kiosk -> Create Square Order -> Create Terminal Checkout -> Payment on Terminal -> payment.updated Webhook -> PaymentCaptureService::capturePayment

Terminal Checkout Details (SquareTerminalAndPayments::createTerminalCheckout):

  1. Requires the device's getSquareTerminalId(); throws if missing
  2. A Square Order is created first (if not already existing) composed WITHOUT tip (includeTip: false), since the tip is collected on-device
  3. A Terminal Checkout is created linking the order to the paired device
  4. Device options: skipReceiptScreen = false, collectSignature = false, and tipSettings built from the location's collect_tips config (on-device tip prompt is configurable, not hard-disabled)
  5. The checkout amount is the transaction total in the smallest currency unit
  6. The referenceId encodes the tenant + order_no (SquareReferenceId) for deterministic webhook routing
  7. The checkout ID and status are stored on the transaction's external_data.square
  8. Payment confirmation arrives via the payment.updated webhook

Retry handling (PaymentService::processSquarePayment): if an existing checkout is PENDING, the transaction is returned without creating a duplicate; if COMPLETED, the transaction is returned as-is; if canceled/failed, a new checkout is created.

Terminal Checkout Statuses (SquareConstants):

  • PENDING -- Checkout created, waiting for terminal
  • IN_PROGRESS -- Customer interacting with terminal
  • CANCEL_REQUESTED -- Cancellation requested
  • CANCELED -- Checkout cancelled
  • COMPLETED -- Payment successful

Cancellation: Terminal checkouts can be cancelled via cancelTerminalCheckout() (wrapped by PaymentService::cancelSquareTerminalCheckout). Cancellation failures are logged but do not throw.

Online Ordering Payments (Square Web Payments SDK)

Customer Order -> Online Ordering -> Square Web Payments SDK (card tokenization) -> POST /online-ordering/payment/process -> OnlineOrderingOrchestrator::processSquarePayment -> SquareIntegrationService::processOnlinePayment -> payment.updated Webhook -> OnlineOrderingOrchestrator::verifyPayment()

The backend processSquarePayment takes the storefront-tokenized source_id and optional verification_token. Square's Web Payments SDK replaces Stripe for online payments -- no Stripe or Viva Wallet configuration is needed.

Not fully verified here: the storefront / proxy code that loads the Square Web Payments SDK and tokenizes the card lives outside these repos; only the backend processSquarePayment/processOnlinePayment path was verified.


Business Rules

  1. Merchant-scoped, not location-scoped: One Square integration covers all locations under the merchant. All locations sync together.
  2. Provider exclusivity: When Square is connected, the merchant's provider_integrated is set to square, routing payments to Square instead of other providers.
  3. Token management: Access tokens have an expiration. The integration stores expires_at and refresh_token_expires_at (under credentials) for token lifecycle management.
  4. Sandbox vs Production: Determined by config('square.sandbox'). Sandbox uses connect.squareupsandbox.com; production uses connect.squareup.com.
  5. Sync is non-destructive: The sync direction algorithm avoids overwriting newer changes. Conflicts are resolved by timestamps and webhook context.
  6. Webhook deduplication: Event IDs are cached for 24 hours to prevent duplicate processing.
  7. Anti-recursion: Cache-based timestamps skip webhook processing within 10 seconds (location/catalog) or 15 seconds (inventory) of a push to Square.
  8. Sync logs: The integration keeps the last 1000 log entries. Consecutive duplicate logs update the timestamp instead of creating new entries.
  9. Full sync order: Test connection -> Locations -> Menus -> Inventory -> update sync status (then fires ReloadMenu per location).
  10. SyncSquareIntegrationJob: Runs with 3 retries, a 600-second (10-minute) timeout, and afterCommit.
  11. No app fee / commission: There is no app_fee_money / commission logic in the current Square payment code.

Square-Specific Features

Terminal Integration

  1. Go to Device Management -> Devices (/device-management/devices)
  2. Select a device and open the Square Terminal section
  3. Click Generate Device Code -- a pairing code is created (POST /devices/.../square-device-code)
  4. Enter the code on the Square Terminal
  5. Once paired, the device.code.paired webhook confirms the connection and the terminal is ready

Catalog Sync

  • Items, categories, modifier groups, variant groups sync per-entity
  • Changes in Upvendo push to Square (via SyncSquareMenuJob or full sync)
  • Changes in Square pull to Upvendo (via catalog webhooks / full sync)
  • Conflict resolution: timestamp + hash comparison; webhook-triggered changes from Square win in conflict

Inventory Sync

  • Stock levels sync per item variation per location
  • Webhook-triggered for targeted updates (SyncSquareInventoryJob); also part of the full sync

Daily Auto-Sync

  • Configurable sync time on the Square page -> Settings tab
  • Runs a full sync: connection test -> locations -> menus -> inventory
  • Driven by the InHouseAutoSyncCommand (in-house:auto-sync) scheduler, which calls startSync() directly. Auto-sync is skipped after 3 consecutive failures.

FAQs

Do I need to set up a payment profile for Square?

No. Square handles all payments directly. You do not need to configure Stripe, Viva Wallet, or any other payment provider when Square is connected.

What happens when I connect Square for the first time?

After OAuth authorization, a full sync runs automatically: Square locations are imported with their data, the menu catalog is synced, and inventory levels are reconciled. This may take a few minutes depending on the size of your catalog.

Can I create items in Upvendo and push them to Square?

Yes. Items created in Upvendo are pushed to Square on the next sync (manual or daily); items created in Square are pulled to Upvendo. The direction is decided automatically per entity.

How does conflict resolution work?

When both sides changed the same entity since the last sync: in webhook context (Square just changed), Square wins; in manual sync context, the most recently modified side wins based on timestamps.

What data does Square NOT provide?

Square does not provide branding data like logos, colors, or fonts. Configure these manually in the Upvendo Branding Profile after locations are imported.

Can I use Square for only kiosk OR only online ordering?

Yes. Square handles both, and you configure which channels are active per location. Payment routing adapts based on the order channel.

How often does the daily sync run?

Once per day at the time configured on the Settings tab. The sync time must be HH:00 or HH:30.

What happens if I disconnect Square?

Disconnecting revokes the Square token, deletes the integration record, and clears the merchant's provider_integrated. No more payment processing until an alternative (Stripe, Viva Wallet) is configured. Sync also stops.


Troubleshooting

"OAuth connection failed"

  • Verify the Square account is active and in good standing
  • Ensure you have owner/admin permissions on the Square account
  • Try disconnecting and reconnecting from the Square page (/square)
  • Check that the Square Application ID and Secret are configured in the backend (config/square.php)
  • For sandbox: have a sandbox seller dashboard open in another browser tab

"Locations not appearing after connecting"

  • The first sync runs automatically -- check the sync status on the Square page -> Status tab
  • If sync shows "in progress" for too long, check the logs for errors
  • Click Sync Now to trigger a manual sync
  • SyncSquareIntegrationJob has a 10-minute timeout -- check if it timed out
  • Trigger a manual sync: Square page -> Status tab -> Sync Now
  • Items created in either system sync per the direction algorithm
  • Check the daily sync time on the Settings tab
  • Review sync logs for specific item errors
  • For single-entity sync issues, check the SyncSquareMenuJob logs (3 retries, 60-second backoff)

"Payments not processing"

  • Verify the location is synced with Square (it should have a Square external ID)
  • Check the Square Dashboard for account holds or verification requirements
  • For kiosk: ensure the Square Terminal is paired and online
  • Check that the payment.updated webhook is being received and processed

"Square Terminal not connecting"

  • Ensure the terminal is powered on and connected to the internet
  • Generate a new device code if the previous one expired
  • The terminal must be signed into the same Square account connected to Upvendo
  • Pairing is confirmed via the device.code.paired webhook -- the device record should show a pending device code before pairing

"Inventory counts are wrong"

  • Trigger a manual sync to reconcile counts with Square
  • Check that the item variation has a Square external ID (unsynced items won't have inventory)
  • Verify the correct Square location is mapped to the Upvendo location
  • Note the anti-recursion cooldown -- inventory webhooks are skipped within 15 seconds of a push

"Sync seems stuck or running too long"

  • SyncSquareIntegrationJob has a 10-minute timeout
  • Check sync logs on the Status tab for errors
  • If the job failed, it retries up to 3 times
  • Click Sync Now to start a fresh sync
  • Check the queue worker is running and processing jobs

"Changes in Square are not reflected in Upvendo"

  • Verify the verify.square-webhook middleware is not rejecting Square webhooks (signature key mismatch)
  • Check that the webhook URL POST /webhook/square is registered in the Square Developer Dashboard
  • The anti-recursion cache may be blocking the webhook (10s catalog/locations, 15s inventory)
  • Trigger a manual sync to force a reconcile from Square

Disconnecting Square

If you need to disconnect Square:

  1. Go to Square (/square) -> Settings tab
  2. Click Delete and confirm
  3. This revokes the Square token, deletes the integration, and removes Square as the payment provider

Warning: Disconnecting Square means:

  • No more payment processing (kiosk and online) until an alternative is configured
  • Sync stops
  • Set up Stripe (online) and/or Viva Wallet (kiosk) as alternatives before disconnecting

Note: disable() aborts if a sync is currently in_progress.


Assistant Guidance

When helping users with Square integration:

  • Square is merchant-scoped -- one connection covers all locations. Do not suggest per-location setup.
  • The first sync after OAuth runs automatically. If locations or items are missing, suggest a manual Sync Now.
  • For payment issues, check that the location has a Square external ID and (for kiosk) the terminal is paired.
  • Square handles all payments -- do not suggest configuring Stripe or Viva Wallet while Square is active.
  • There are no per-data-type sync toggles, no location picker, and no sync-direction setting -- do not tell users to change these.
  • Conflict resolution favors Square in webhook context and most-recent-change in manual sync.
  • Branding (logos, colors, fonts) must be set manually -- Square does not provide these.

Relations