# 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=<YOUR_AUTH_CODE>" \
  -d "client_id=<YOUR_CLIENT_ID>" \
  -d "client_secret=<YOUR_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 integration is OFF by default — set to true to enable
ZOHO_ENABLED=false
ZOHO_API_DOMAIN=https://www.zohoapis.com
ZOHO_ACCOUNTS_DOMAIN=https://accounts.zoho.com
ZOHO_CLIENT_ID=<from Step 1>
ZOHO_CLIENT_SECRET=<from Step 1>
ZOHO_REFRESH_TOKEN=<from Step 3>
# Cases forwarding is also OFF by default
ZOHO_CASES_ENABLED=false
```

> **Note:** Both `ZOHO_ENABLED` and `ZOHO_CASES_ENABLED` default to `false`. Set them to `true` only after completing Steps 1–3 and verifying your credentials.

### 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:
1. Deploy the environment variables to production
2. Set `ZOHO_ENABLED=true` and `ZOHO_CASES_ENABLED=true` in production `.env`
3. Restart the application
4. Submit a test lead and support case to verify data flows to Zoho CRM
5. Check Zoho CRM Leads and Cases tabs to confirm both appear

---

**Need help?** Contact your site administrator.
