OAuth & Webhook Flows
This page describes implemented flows in apps/api and apps/web.
Square Connect Flow
OAuth State Security
State is HMAC-signed and expiring (10-minute TTL), not trusted blindly.
If state validation fails, callback redirects with failure diagnostics.
OAuth Host Safety
Authorization URL host is hard-guarded to:
connect.squareupsandbox.comconnect.squareup.com
Web client also validates/normalizes URL before redirect.
Webhook Flow
Route: POST /api/v1/webhooks/square
This is a fast-ack model with asynchronous processing to keep provider retries low.
Poll Fallback
Route: POST /api/v1/internal/cron/square-poll-payments
- protected by
X-Cron-Secret - scans active Square connections
- refreshes expiring access tokens when needed (180s buffer)
- calls
ListPaymentsusing watermark checkpoint (clamped tonow()) - executes same ingestion path as webhooks
Webhook Retry Sweeper
Route: POST /api/v1/internal/cron/process-pending-webhooks
- protected by
X-Cron-Secret - claims due
webhook_jobsrows (pending, failed and ready, or staleprocessing) - caps at 200 jobs per run
- routes by provider to
processSquareWebhookorprocessCloverWebhook - retries failures with backoff
- both processors are idempotent through
idempotency_keys; safe to retry
Accepted webhooks are ingested immediately after the 200. This route retries jobs that did not finish. Square and Clover payment polls remain the fallback when a webhook never arrives.
Clover Poll Fallback
Route: POST /api/v1/internal/cron/clover-poll-payments
- protected by
X-Cron-Secret - scans active Clover connections
- lists payments modified since
clover_payments_watermark_at - runs them through the same idempotent ingestion path as webhooks
- holds the watermark when a payment is still settling
Clover Integration
Clover OAuth, webhook receive, payment polling, and ingestion are implemented. See POS Integrations for notification-only webhook payloads, REST payment fetch, signature verification, and multi-merchant rejection.