Data handling disclosure

How TimeCinch handles your Lightspeed data

Last updated: June 2, 2026

This page explains exactly what data TimeCinch reads from your Lightspeed Retail (X-Series) account, what we store, how long we keep it, what we transmit back to Lightspeed, and what we never touch. It accompanies our Lightspeed marketplace listing and is updated whenever the integration's data surface changes.

The short version

  • We never see, store, or transmit payment card numbers, CVVs, or any other cardholder data.
  • We mirror customers, sales, products, and org metadata into an encrypted Supabase Postgres database.
  • OAuth tokens are stored encrypted at rest; refresh tokens rotate on every use.
  • Webhook signatures are verified with HMAC-SHA256 and a timing-safe compare before any side effect.
  • Disconnecting the integration voids your Lightspeed webhook subscriptions and removes mirrored data via foreign-key cascade.

1. OAuth scopes we request, and why

When a merchant connects Lightspeed, we redirect them to Lightspeed's OAuth consent screen with the scopes listed below. The authoritative source for this list is DEFAULT_SCOPES in lib/lightspeed/auth.ts.

ScopePurpose
customers:readMirror customers locally so appointment bookings can be linked to the correct Lightspeed customer record. Also reads loyalty balances stored on the customer object.
customers:writeCreate new customers in Lightspeed when a client books for the first time via TimeCinch. Update names, contact details, and TimeCinch-managed tags.
products:readMirror the product catalog so merchants can map services and back-bar products to Lightspeed SKUs.
sales:readPull historical sales (last 90 days at connect-time) and listen for sale-status changes (paid, voided, refunded). Used to keep appointments in sync.
sales:writePush appointment sales to the merchant's Lightspeed register so they can be paid through Lightspeed's existing checkout flow.
outlets:readResolve the correct outlet ID when pushing a sale. Required by the Lightspeed Sales API.
registers:readResolve the correct register ID when pushing a sale so it appears at the right station.
users:readAttribute pushed sales to the right Lightspeed user (the staff member who performed the service).
taxes:readApply the correct tax rate ID per sale line. Required by the Lightspeed Sales API.
inventory:readSurface stock counts beside service ↔ product mappings in TimeCinch.
gift_cards:readLook up the current balance of a gift card at appointment-checkout time so the customer can redeem against the sale.
gift_cards:writeApply the gift card as a payment line when the sale is pushed (splits the payment onto the gift_card payment type).
webhooksRegister webhook subscriptions on the merchant's Lightspeed account so we receive changes (sales, customers, products, inventory) in real time.

2. Data we read from Lightspeed and store

We maintain local mirrors of a small set of entities in our Supabase Postgres database. Mirroring is required because Lightspeed's rate limits make it impractical to query every appointment-related screen against Lightspeed's API directly. All data is encrypted at rest using Supabase's standard AES-256 disk encryption.

EntityStored asRetention
OAuth connectionlightspeed_connectionsUntil disconnect; tokens encrypted at rest.
Customerslightspeed_customersUntil disconnect; cascade-deleted on disconnect.
Sales (mirrored)lightspeed_salesRolling 90-day window; cascade-deleted on disconnect.
Productslightspeed_productsUntil disconnect; cascade-deleted on disconnect.
Outlets, registers, users, taxeslightspeed_outlets / _registers / _users / _taxesUntil disconnect; cascade-deleted on disconnect.
Sync log (operational)lightspeed_sync_logRolling 30-day window for troubleshooting; never contains tokens.

All mirror tables have a foreign key onto lightspeed_connections with ON DELETE CASCADE. When a merchant disconnects, every row tied to their connection is removed in a single transaction.

3. Data we send to Lightspeed

Writes only happen through documented, scoped X-Series API endpoints. We never call undocumented routes or scrape the merchant UI.

  • Customer create / update — name, email, phone, and TimeCinch-managed tags (tc:* prefixed). We do not modify non-tc: tags set by the merchant.
  • Sale create / update— line items, prices, tax IDs, register ID, user ID, outlet ID, and (optionally) gift-card payment split. Used to ring up appointments through the merchant's normal Lightspeed checkout.
  • Inventory adjustments — quantity decrements for back-bar products consumed during an appointment.
  • Webhook subscriptions — created at connect time, voided on disconnect.

4. Data we never touch

The following are out of scope for the TimeCinch integration. We never read, store, log, or transmit:

  • Payment card data— PAN, CVV, expiry, track data, tokenized cards. All payment-related work happens inside Lightspeed's PCI environment and never transits our systems.
  • Bank account / payout / settlement data.
  • Lightspeed user passwords, MFA secrets, or session tokens.
  • Employee timesheet, payroll, or HR data (we don't request the relevant scopes).
  • Suppliers, purchase orders, or supplier pricing(we don't request the relevant scopes).

5. Token handling

  • Access and refresh tokens are stored in the lightspeed_connections table. The columns are encrypted at rest using Supabase's built-in column encryption (AES-256-GCM via the platform's managed key).
  • Refresh tokens are single-use. We rotate them on every refresh, write the new token in the same transaction that consumes the old one, and never log token values. See refreshAccessToken in lib/lightspeed/auth.ts.
  • Access tokens are refreshed eagerly when within 60 seconds of expiry, so we never make a Lightspeed call with a near-expired token.
  • Tokens are accessible only to our server-side runtime (Vercel Node.js functions). They are never exposed to the browser or returned in any client-facing response.

6. Webhook signature verification

Lightspeed signs every webhook delivery with an X-Signature header containing an HMAC-SHA256 hash of the raw request body, keyed with our OAuth client secret. Our webhook handler:

  • Reads the raw body (no JSON parsing first — required for the HMAC to match).
  • Computes the expected HMAC and compares it against the provided signature using node:crypto.timingSafeEqual.
  • Returns 401 on any signature failure and does not write to the database.
  • Returns 2xxfor valid signatures within Lightspeed's 5-second budget, even when the inner payload is for an unknown event type.

Source: verifyWebhookSignature in lib/lightspeed/webhooks.ts; handler in app/api/lightspeed/webhook/route.ts.

We currently subscribe to the following webhook event types: sale.update, customer.update, product.update, inventory.update.

7. Breach notification

In the event we discover a confirmed or suspected breach involving Lightspeed merchant data, we will:

  • Notify affected merchants within 72 hoursof confirmation, by email to the business owner's registered address.
  • Notify Lightspeed's partner security contact in the same window.
  • Revoke and rotate the affected OAuth credentials, force a token refresh on every merchant, and preserve forensic logs.
  • Publish a remediation summary within 30 days.

Security contact: hello@timecinch.com (subject line: “SECURITY” for prioritization).

8. Disconnection & right to be forgotten

Merchants can disconnect TimeCinch from Lightspeed at any time, from either side:

  • In TimeCinch: Settings → Integrations → Disconnect. This calls our /api/lightspeed/disconnect endpoint, which (a) revokes every webhook subscription on the merchant's Lightspeed account, (b) deletes the row in lightspeed_connections, which (c) cascades to remove every mirror row tied to that connection.
  • In Lightspeed: revoke the TimeCinch app from your account's authorized integrations list. Our next API call will receive a 401, after which we mark the connection disconnected, drop our tokens, and stop writing.
  • Full account deletion: if you delete your TimeCinch account, all Lightspeed-linked data is removed as part of the account-deletion cascade. Email hello@timecinch.com to request immediate deletion outside the in-app flow.

9. Infrastructure & subprocessors

  • Vercel — application hosting (Node.js serverless functions). Data in transit only; no persistent storage.
  • Supabase — Postgres database with AES-256 encryption at rest, TLS in transit, row-level security policies on every table.
  • Sentry — error reporting. We scrub tokens and PII from error payloads before they leave our runtime.

10. Verifiable source references

For Lightspeed marketplace reviewers, the canonical source of truth for everything on this page lives in these files:

ClaimSource
OAuth scope setlib/lightspeed/auth.ts → DEFAULT_SCOPES
Single-use refresh rotationlib/lightspeed/auth.ts → refreshAccessToken
Webhook signature verification (HMAC-SHA256)lib/lightspeed/webhooks.ts → verifyWebhookSignature
Webhook event subscription setlib/lightspeed/webhooks.ts → WEBHOOK_EVENT_TYPES
Webhook receiver / 401 on bad signatureapp/api/lightspeed/webhook/route.ts
Disconnect endpoint (revoke + cascade)app/api/lightspeed/disconnect/route.ts
OAuth handshakeapp/api/lightspeed/oauth/start/route.ts + callback/route.ts
Health endpointapp/api/health/lightspeed/route.ts

The runtime health endpoint at /api/health/lightspeed also returns the current scope set and endpoint paths programmatically.

11. Contact