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
- Trigger: SuperOffice sends a webhook (
contact.created,contact.changed,person.created,person.changed) tohttps://floke-ai.duckdns.org/connector/webhook. - Reception:
webhook_app.py(FastAPI) receives the event, validates theWEBHOOK_TOKEN, and pushes a job to the SQLite queue (connector_queue.db). - Processing:
worker.py(v1.9) polls the queue, filters for relevance, fetches details from SuperOffice, and calls the Company Explorer for AI analysis. - 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 newcontact.changedwebhook, 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, oruserdef_id(UDFs) trigger processing. - Persons: Only changes to
jobtitle,position_id, oruserdef_idtrigger processing. - All other events are instantly marked as
SKIPPED(visible in Dashboard).
- Contacts: Only changes to
📊 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
COMPLETEDif at least one job was successful, even if subsequent "echo" webhooks wereSKIPPED.
🐞 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).udlist331returned 404. - Mailing Identity: Resolve 500 error on
Associate/Me. Required for automated "Send As" mailing functionality. - Docker Build: Optimize
connector-superofficebuild 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)