# Zoho CRM Setup Guide for Queue North Admins This guide walks you through setting up Zoho CRM integration to automatically capture leads and support cases from Queue North's website. --- ## 🔒 Prerequisites Before you begin, ensure you have: - A Zoho CRM account (admin access required) - Access to Zoho API Console: https://api-console.zoho.com --- ## Step 1: Create a Zoho Self-Client App 1. Go to **https://api-console.zoho.com** 2. Click **"Create Self Client"** 3. Fill in: - **Client Name**: Queue-North-Zoho-Integration - **Description**: Auto-capture leads and cases from Queue North website - **Redirect URI**: `https://www.zoho.com` (required for Self-Client, not used) 4. Click **Create** 5. **Copy and save**: - **Client ID** - **Client Secret** > ⚠️ Store these securely — they're like a username and password. --- ## Step 2: Generate an Authorization Code 1. In the Self Client tab, click **"Generate Code"** 2. Set the **Scope** to: ``` ZohoCRM.modules.leads.CREATE,ZohoCRM.modules.leads.READ,ZohoCRM.modules.cases.CREATE,ZohoCRM.modules.cases.READ ``` 3. Set **Expiry** to **10 minutes** (use it quickly) 4. Click **Generate** 5. **Copy the authorization code** — it expires in 10 minutes --- ## Step 3: Exchange Auth Code for Tokens Run this `curl` command (replace placeholders): ```bash curl -X POST https://accounts.zoho.com/oauth/v2/token \ -d "code=" \ -d "client_id=" \ -d "client_secret=" \ -d "grant_type=authorization_code" \ -d "redirect_uri=https://www.zoho.com" ``` **Response will include:** ```json { "access_token": "1000.xxxxx.xxxxx", "refresh_token": "1000.yyyyy.yyyyy", "expires_in": 3600, "token_type": "bearer" } ``` **Save the `refresh_token`** — this never expires and must be kept secret. --- ## Step 4: Configure Environment Variables Add these to your `.env` file: ```env ZOHO_ENABLED=true ZOHO_API_DOMAIN=https://www.zohoapis.com ZOHO_ACCOUNTS_DOMAIN=https://accounts.zoho.com ZOHO_CLIENT_ID= ZOHO_CLIENT_SECRET= ZOHO_REFRESH_TOKEN= ZOHO_CASES_ENABLED=true ``` ### Datacenter Variants If your Zoho datacenter is **outside the US**, adjust the domains: | Region | API Domain | Accounts Domain | |--------|-----------|-----------------| | US | `www.zohoapis.com` | `accounts.zoho.com` | | EU | `www.zohoapis.eu` | `accounts.zoho.eu` | | IN | `www.zohoapis.in` | `accounts.zoho.in` | | AU | `www.zohoapis.com.au` | `accounts.zoho.com.au` | --- ## Step 5: Test the Integration ### Test Lead Capture 1. Submit a lead on the contact form (name, email, phone, message) 2. Wait ~5–10 seconds 3. Log in to Zoho CRM → Leads tab 4. Verify the new lead appears with correct data ### Test Case Capture 1. Submit a support request (e.g., booking inquiry, technical question) 2. Wait ~5–10 seconds 3. Log in to Zoho CRM → Cases tab 4. Verify the new case appears with correct data --- ## Troubleshooting ### Token Errors - **"invalid_grant"**: Your authorization code expired. Generate a new one in Step 2 and repeat Step 3. - **"invalid_client"**: Double-check Client ID and Secret — no extra spaces. - **"invalid_scope"**: Re-run Step 2 with the exact scopes listed above. ### Field Mismatches - If leads/cases don't appear, check if Zoho requires custom fields like `Service_Interest` - Edit the field mapping in `server/zoho/` to match your Zoho CRM field API names ### Cases Not Appearing - Ensure `ZOHO_CASES_ENABLED=true` is set - Verify the Cases tab is enabled in your Zoho CRM plan - Check that your Zoho CRM user has **Cases CREATE** permissions ### Lead Upsert Behavior - Leads are **upserted by email**: duplicate email = update existing lead - Cases are **always inserted** (new ticket each time) - If you see duplicate leads, check for slight email variations (e.g., `test@` vs `test+1@`) --- ## Architecture Notes ### Flow Overview ``` Website Contact Form → SQLite (always saved) ↓ Zoho CRM (best-effort) ↓ Fire-and-forget (no failure blocking) ``` ### OAuth2 Refresh Token Flow 1. Use `refresh_token` to get a new `access_token` when expired 2. `access_token` expires in 1 hour 3. `refresh_token` never expires — store it securely ### Upsert Logic - **Leads**: Email-based upsert (update if exists, create if new) - **Cases**: Always insert (new case per submission) ### Fire-and-Forget Design - Zoho failures **do not block** form submissions - All data is saved to SQLite first - Zoho attempts happen in the background - No retry logic needed — users won't wait for Zoho --- ## What Happens Next? After configuration, your team (Ripley + Bishop) will: 1. Deploy environment variables to production 2. Run integration tests 3. Verify data flows to Zoho CRM 4. Update `PROJECT.md` with the integration status --- **Questions?** Contact Ripley (Infrastructure) or Neo (Backend).