Ad & billing OAuth setup (operator)
Register one OAuth app per provider, once. The credentials become platform secrets (wrangler secret put), set on both the staging and production API workers. Until they're set, the connect flow shows "… isn't enabled on this workspace yet" and the OAuth start endpoint returns 503 CONNECTOR_OAUTH_NOT_CONFIGURED (it never redirects to a broken provider page).
Clients never see these — they just click Connect and approve their own account.
Callback (redirect) URIs
Whitelist these exactly (they're derived from ENVIRONMENT):
| Provider | Staging | Production |
|---|---|---|
| Meta Ads | https://api-sta.kordox.com/api/oauth/facebook-ads/callback | https://api.kordox.com/api/oauth/facebook-ads/callback |
| Google Ads | https://api-sta.kordox.com/api/oauth/google-ads/callback | https://api.kordox.com/api/oauth/google-ads/callback |
| Stripe | https://api-sta.kordox.com/api/oauth/stripe/callback | https://api.kordox.com/api/oauth/stripe/callback |
| Shopify | https://api-sta.kordox.com/api/oauth/shopify/callback | https://api.kordox.com/api/oauth/shopify/callback |
Meta Ads — Meta for Developers
- developers.facebook.com → Apps → Create app → type Business.
- Add the Facebook Login product; under its settings add the two Meta redirect URIs above.
- Permissions used by the connector:
ads_read,leads_retrieval,pages_manage_ads(spend sync + lead-gen forms).ads_read/leads_retrievalare advanced-access scopes → require App Review + a Business verification before non-test users can grant them. Test users work immediately. - Set secrets:bash
cd apps/api npx wrangler secret put FACEBOOK_APP_ID npx wrangler secret put FACEBOOK_APP_SECRET # prod: append --env production
Spend now syncs per campaign (level=campaign insights) → powers per-campaign ROAS. First sync pulls ~30 days.
Google Ads — Google Cloud + Google Ads API
- Google Cloud Console → OAuth client (Web application); add the two Google redirect URIs above. Scope:
https://www.googleapis.com/auth/adwords. - Apply for a Google Ads API developer token (Google Ads account → API Center). Starts in test access; basic access needs an application review.
- Set secrets:bash
cd apps/api npx wrangler secret put GOOGLE_ADS_CLIENT_ID npx wrangler secret put GOOGLE_ADS_CLIENT_SECRET npx wrangler secret put GOOGLE_ADS_DEVELOPER_TOKEN # prod: append --env production
Spend syncs per campaign (FROM campaign, metrics.cost_micros).
Stripe Connect — Stripe dashboard
- Stripe → Settings → Connect → enable; copy the Connect client ID (
ca_…). Add the Stripe redirect URIs above. - Set secrets:bash
cd apps/api npx wrangler secret put STRIPE_CLIENT_ID # ca_... npx wrangler secret put STRIPE_SECRET_KEY # sk_... (token exchange) # prod: append --env production
Shopify — Partners dashboard
- partners.shopify.com → Apps → Create app; add the Shopify redirect URIs.
- Set secrets:bash
cd apps/api npx wrangler secret put SHOPIFY_CLIENT_ID npx wrangler secret put SHOPIFY_CLIENT_SECRET # prod: append --env production
Verify
After setting secrets, GET /api/financial/accounts returns oauthConfigured: { stripe, shopify, "facebook-ads", "google-ads" } — the connect modal reads this and enables the provider. Connect a test account, then Sync now; per-campaign spend appears on Finance → Campaign attribution.
Routes: apps/api/src/routes/oauth.ts; connectors: apps/api/src/connectors/{facebook-ads,google-ads,stripe,shopify}.ts; config gate: oauthProvidersConfigured() in apps/api/src/connectors/base.ts.