Construir un conector
Guía técnica para integradores: cómo construir desde cero un conector que traiga datos externos al ecosistema y los deje disponibles en las fichas y en el bot.
Un conector es cualquier integración que trae datos de un sistema externo (MercadoPago, TiendaNube, Google Analytics, un banco, un broker) al ecosistema del usuario. Este artículo es para developers e integradores. Si sos usuario y solo querés conectar tus sistemas, mirá el artículo de usuario.
Antes de escribir código
Definí estas cuatro cosas antes de tocar el editor:
- Tipo. Los tipos soportados son
rest_api,mcpywebhook. La mayoría son REST vía OAuth2 o API key. Email Ingest ya está implementado aparte (/api/ingest/). - Scope. Todo conector tiene un scope:
profile,entityo ambos. Se declara enconnector_field_map, junto con sipropagates_to_children. Las credenciales nunca cruzan scopes: si el conector es de scopeentity, sus credenciales solo se usan dentro de esa entidad, y RLS lo refuerza. - Mapa de campos. Definí exactamente qué campos alimenta el conector en
connector_field_mapantes de escribir una línea. Se seedea en la migración. - Audit. Cada conexión y desconexión se registra en
connector_scope_audit. El conector tiene que llamar a esa función al conectar y al desconectar.
Los pasos
- Migración de la tabla. Creá la tabla de credenciales del conector con RLS activado (política por
profile_id = auth.uid()). Guardá estado de sync (sync_statuscon CHECKpendiente | sincronizando | ok | error),ultima_syncy metadata. Pobláconnector_field_mapen la misma migración. - Autenticación. Implementá OAuth2 (una ruta que redirige a la autorización externa + un
callbackque intercambia elcodepor token) o API key. Antes de guardar, encriptá el token: AES-256-GCM conencrypt/decryptde@/lib/encryption, guardandocredentials_enc,credentials_ivycredentials_tag. Nunca en texto plano, nunca en el frontend. - Sincronización. En la ruta de
sync:checkRateLimitde@/lib/rate-limitantes de cada llamada externa, desencriptá el token, llamá a la API y guardá cada registro enconnector_snapshotsconexternal_id(ID en el sistema externo) yconnector_source(slug del conector), cononConflictpara idempotencia. Los snapshots son diarios, con UNIQUE(connector_id, snapshot_date). Al terminar, actualizásync_status. Dejá un fallback graceful si la API externa no responde. - Field contributions. Los datos que alimentan las fichas no se escriben directo a las tablas de dominio: van a
field_contributionsconsource_type = 'connector',source_id= slug del conector, yscope_level/scope_idcorrectos. Al instalar el conector, la auto-conexión crea estas contribuciones automáticamente. - Tools del bot. Registrá las tools del conector en
connector_tools(nombre, descripción,endpoint_url,auth_type,category,required_entity_types) cononConflict('connector_name,name'). El bot carga las tools activas del usuario en cada sesión, así puede responder sobre los datos del conector. - UI y catálogo. El conector aparece en el catálogo de
/dashboard/conectoresy en Configuración → Conectores víaConnectorCard. Cambiá sustatusenconnector_catalogdecoming_soonaavailablepara que la card muestre el botón "Conectar".
Catálogo y waitlist
El catálogo vive en connector_catalog (slug, name, description, category, status, icon, waitlist_count). Mientras un conector no existe, los usuarios votan demanda con "Lo necesito": cada voto es una fila en connector_waitlist (profile_id + connector_id UNIQUE) y un trigger actualiza waitlist_count. Endpoints reales:
GET /api/connectors/catalog— catálogo agrupado por categoría, conuser_in_waitlist.POST /api/connectors/waitlist— toggle de voto (INSERT/DELETE).
Estados posibles: available, coming_soon, connected.
Checklist de cierre
Tabla con RLS · credenciales encriptadas · OAuth2/API key · rate limiting antes de cada llamada externa · fallback graceful · datos con external_id y connector_source · tools en connector_tools · UI en Configuración → Conectores · variables de entorno en .env.example · tests de integración en src/__tests__/integration/ · connector_field_map seedeado · auto-conexión crea las field_contributions · connector_scope_audit registra la conexión.
El razonamiento de scopes y fuentes está en DEC-010 y DEC-011.