# SuperOffice Connector README ## Overview This directory contains Python scripts designed to integrate with the SuperOffice CRM API, primarily for data enrichment and lead generation automation. ## 🚀 Production Deployment (March 2026) **Status:** ✅ Live & Operational **Environment:** `online3` (Production) **Tenant:** `Cust26720` ### 1. Architecture & Flow 1. **Trigger:** SuperOffice sends a webhook (`contact.created`, `contact.changed`, `person.created`, `person.changed`) to `https://floke-ai.duckdns.org/connector/webhook`. 2. **Reception:** `webhook_app.py` (FastAPI) receives the event, validates the `WEBHOOK_TOKEN`, and pushes a job to the SQLite queue (`connector_queue.db`). 3. **Processing:** `worker.py` (v1.9) polls the queue, filters for relevance, fetches details from SuperOffice, and calls the **Company Explorer** for AI analysis. 4. **Sync:** Results (Vertical, Summary, hyper-personalized Openers) are patched back into SuperOffice `UserDefinedFields`. ### 2. Operational Resilience (Lessons Learned) #### 🛡️ A. Noise Reduction & Loop Prevention * **Problem:** Every data update (`PATCH`) triggers a new `contact.changed` webhook, potentially creating infinite loops (Ping-Pong effect). Also, irrelevant changes (e.g., phone numbers) waste AI processing resources. * **Solution:** Strict **Whitelist Filtering** in `worker.py`. * **Contacts:** Only changes to `name`, `urladdress`, `urls`, `orgnr`, or `userdef_id` (UDFs) trigger processing. * **Persons:** Only changes to `jobtitle`, `position_id`, or `userdef_id` trigger processing. * All other events are instantly marked as **`SKIPPED`** (visible in Dashboard). #### 📊 B. Dashboard & Sync-Runs * **Problem:** Continuous webhooks created hundreds of messy dashboard entries for the same account. * **Solution:** **Sync-Run Clustering**. * Jobs for the same account occurring within **15 minutes** of each other are grouped into a single "Sync-Run" row. * **Status Prioritization:** A row shows `COMPLETED` if at least one job was successful, even if subsequent "echo" webhooks were `SKIPPED`. #### 🐞 C. The "Unhashable Dict" Mystery * **Incident:** During deployment, a `TypeError: unhashable type: 'dict'` occurred. Initial suspicion was a SuperOffice API bug. * **Resolution:** Deep analysis of raw JSON proved the API is healthy. The error was caused by a bug in the *test/dashboard scripts* (creating a dictionary literal using another dictionary as a key). * **Lesson:** Always verify raw API output (`debug_raw_response.py`) before blaming the vendor. ### 3. Tooling & Diagnosis Located in `connector-superoffice/tools/`: * `verify_enrichment.py`: Verifies if AI data actually landed in SuperOffice (using raw text search). * `create_company.py`: Creates a test company in Prod to trigger the flow. * `full_discovery.py`: Lists all available UDFs and Lists on the current tenant. * `final_truth_check.py`: Validates JSON structure of API responses. * `who_am_i.py`: Identifies the API user's Associate ID. ### 4. Open Todos * [ ] **List ID Mapping:** Identify the correct List ID for the "Vertical" field (ProgID `SuperOffice:83`). `udlist331` returned 404. * [ ] **Mailing Identity:** Resolve 500 error on `Associate/Me`. Required for automated "Send As" mailing functionality. * [ ] **Docker Build:** Optimize `connector-superoffice` build time (>8 mins) using Multi-Stage Dockerfiles to avoid C-compilation on every deploy. --- ## Authentication (Legacy) Authentication is handled via the `AuthHandler` class, which uses a refresh token flow to obtain access tokens. Ensure that the `.env` file in the project root is correctly configured with `SO_CLIENT_ID`, `SO_CLIENT_SECRET`, `SO_REFRESH_TOKEN`, `SO_REDIRECT_URI`, `SO_ENVIRONMENT`, and `SO_CONTEXT_IDENTIFIER`. ## Key SuperOffice Entities and Data Model Observations (See full file for historical notes on Sale Entity and Product Information Storage)