Airbyte · Lightfield (CRM comercial)
Replica el CRM Lightfield (reemplazo de HubSpot desde 2026-10) a
solvento-data-prod.lightfield.*con un conector custom de Airbyte (Connector Builder) y lo modela en dbt-etls haciasolvento-adv-analytics-prod.lightfield.*.
Reemplaza a Airbyte · Hubspot
Lo nuevo del CRM vive acá. Airbyte · Hubspot sigue sincronizando hubspot.* mientras la cuenta esté activa y queda como historia previa al corte: solo se migró una parte de los deals (ver cobertura). La tabla de equivalencias dice qué tabla nueva reemplaza a cada una de HubSpot.
¿Llegaste hasta acá desde…?
| Si ves… | Eso sale de… | La lógica está en… |
|---|---|---|
| Oportunidades / funnel por pipeline y etapa del CRM | solvento-adv-analytics-prod.lightfield.lightfield_opportunities |
dbt-etls → models/advanced_analytics/lightfield/lightfield_opportunities.sql |
Ids como pd_… / opt_… en vez de nombres |
…lightfield.stg_lightfield_select_options |
dbt-etls → …/stg_lightfield_select_options.sql (sale del stream definitions) |
| Cuentas (empresas) del CRM, RFC, línea de crédito, LOC | …lightfield.stg_lightfield_accounts |
dbt-etls → …/stg_lightfield_accounts.sql |
| Owner / responsable comercial | …lightfield.stg_lightfield_members |
dbt-etls → …/stg_lightfield_members.sql |
| Fecha de entrada a cada etapa de un deal migrado | …lightfield.stg_lightfield_opportunity_hubspot_stage_dates |
dbt-etls → …/stg_lightfield_opportunity_hubspot_stage_dates.sql |
Un registro crudo con fields / relationships en JSON |
solvento-data-prod.lightfield.* (RAW) |
Airbyte (sin lógica de negocio); ver "Paso a paso" |
| Campo | Valor |
|---|---|
| Origen | API REST de Lightfield (https://api.lightfield.app/v1, header Lightfield-Version: 2026-03-01) |
| Patrón | Airbyte con conector custom (Connector Builder, manifest declarativo) — sin lógica de negocio en la ingesta |
| Destino RAW | solvento-data-prod.lightfield.* (5 tablas) |
| Destino dbt | solvento-adv-analytics-prod.lightfield.* (6 tablas, tag:lightfield) |
| Frecuencia | Airbyte cada 6 h (confirmar en Airbyte; es lo que muestra _airbyte_extracted_at) · dbt-etls con el job diario de dbt Cloud |
| Criticidad | 🟢 Baja hoy (todavía nadie lee de producción); sube a 🟡 Media cuando crédito migre |
| Dueño | Martin (conector y dbt-etls) · consumo en crédito y analytics: Diego |
| Repos | dbt-etls · manifest del conector en lightfield-airbyte (pendiente de subir a GitLab) |
Diagrama de linaje
graph LR
SRC[["📇 Lightfield<br/>API REST v1"]]
subgraph ing["1 · Ingesta (sin lógica de negocio)"]
AB["Airbyte<br/>conector custom<br/>(Connector Builder)"]
RAW[("solvento-data-prod.lightfield<br/>accounts · contacts · opportunities<br/>members · definitions")]
end
subgraph logica["2 · Lógica · dbt-etls (tag:lightfield)"]
STG[("adv-analytics.lightfield<br/>stg_lightfield_* (5)<br/>JSON → columnas")]
OPP[("adv-analytics.lightfield<br/>lightfield_opportunities<br/>labels · owner · RFC")]
end
CONS["📈 Funnels · crédito (DSCR) · Meowth<br/>(migrando desde hubspot.*)"]
SRC -->|"Bearer · 25 por página<br/>$updatedAt · cada 6 h"| AB --> RAW --> STG --> OPP --> CONS
classDef src fill:#fde68a,stroke:#b45309,color:#000;
classDef store fill:#bfdbfe,stroke:#1e40af,color:#000;
class SRC src;
class RAW,STG,OPP store;
Paso a paso
1 · Ingesta (mueve datos, no aplica lógica de negocio)
- Lightfield expone el CRM por API REST. La key está en Secret Manager como
lightfield_api_keyy se configura en el conector, no en código. - Airbyte corre un conector custom armado en el Connector Builder (manifest declarativo). Las decisiones salen de un probe de la API (2026-10-02):
- Paginación por
offsetconlimit=25, que es el máximo (26 da400 limit_too_large). El orden es fijo porcreatedAtdescendente y estable entre requests. - Incremental server-side con
$updatedAt[greaterThan]. El$es obligatorio: sin él la API responde400 "Unknown filter field". Lookback de 1 h para no perder updates en vuelo. - Streams:
accounts,contactsyopportunitiesen Incremental | Append + Deduped porid;membersydefinitionsen Full refresh | Overwrite. - Rate limit: 25 req/s por categoría y organización; ~1,4 s por página. Una sync completa de
accounts(~19.000 registros) tarda del orden de 18 min (estimado: ~750 páginas × 1,4 s).
- Paginación por
- Cada registro llega con
fieldsen JSON ({slug: {valueType, value}}) yrelationshipsen JSON ({slug: {cardinality, objectType, values}}). Un campo nuevo en Lightfield entra solo dentro del JSON, sin tocar el esquema. definitionstrae una fila por objeto (accounts,contacts,opportunities) confieldDefinitionsyrelationshipDefinitions. Es la única fuente de los labels: los registros traen los selects como ids (pd_…para pipelines,opt_…para etapas y opciones).
2 · Lógica de negocio (dbt — aquí están las reglas) → repo dbt-etls
Todo en models/advanced_analytics/lightfield/, materializado como table en solvento-adv-analytics-prod.lightfield. El tag es por carpeta en dbt_project.yml: dbt build --select tag:lightfield.
stg_lightfield_opportunities— una fila por oportunidad. Deja afuera el texto generado por IA ($opportunityStatus) y las relaciones que vienen vacías.stg_lightfield_accounts— una fila por cuenta.is_from_hubspot(tienehubspot-company-id) yhas_captured_activity(correos o reuniones capturados por Lightfield) separan lo útil del ruido.stg_lightfield_members— los owners, con nombre y email.stg_lightfield_select_options— catálogo de opciones de todos los selects;option_orderes el orden de Lightfield.stg_lightfield_opportunity_hubspot_stage_dates— las fechashs-v2-date-entered-<id>importadas de HubSpot, en formato largo. El grano (oportunidad, etapa) se verifica entests/test_lightfield_stage_dates_grain_unique.sql.lightfield_opportunities— la tabla de uso: pipeline y etapa con label,stage_orderdentro del pipeline, producto y origen con label, owner con nombre yrfcde la oportunidad o, si falta, de la cuenta (rfc_source).
3 · Consumo
- Al 2026-10-05 no hay consumidores productivos. Diego migra los procesos de crédito (DSCR) y los funnels que leen de
hubspot.*; la tabla de equivalencias de abajo es el punto de partida.
Tablas que alimenta
| Tabla | Contenido | Cómo se carga |
|---|---|---|
lightfield.accounts (RAW) |
Cuentas (empresas) | Airbyte (incremental + dedup) |
lightfield.contacts (RAW) |
Contactos (sin modelo dbt todavía) | Airbyte (incremental + dedup) |
lightfield.opportunities (RAW) |
Oportunidades (deals) | Airbyte (incremental + dedup) |
lightfield.members (RAW) |
Usuarios del workspace | Airbyte (full refresh) |
lightfield.definitions (RAW) |
Definiciones de campos y relaciones por objeto | Airbyte (full refresh) |
adv-analytics.lightfield.stg_lightfield_opportunities |
1 oportunidad por fila, con ids | dbt-etls (table) |
adv-analytics.lightfield.stg_lightfield_accounts |
1 cuenta por fila | dbt-etls (table) |
adv-analytics.lightfield.stg_lightfield_members |
1 usuario por fila | dbt-etls (table) |
adv-analytics.lightfield.stg_lightfield_select_options |
1 opción de select por fila | dbt-etls (table) |
adv-analytics.lightfield.stg_lightfield_opportunity_hubspot_stage_dates |
1 fila por oportunidad y etapa de HubSpot | dbt-etls (table) |
adv-analytics.lightfield.lightfield_opportunities |
Tabla de uso. Oportunidades con labels, owner y RFC | dbt-etls (table) |
Equivalencias con HubSpot
HubSpot (solvento-data-prod.hubspot / dbt-analytics) |
Lightfield (solvento-adv-analytics-prod.lightfield) |
Notas |
|---|---|---|
hubspot.deals · stg_hubspot__deals · int_hubspot_deals |
stg_lightfield_opportunities (ids) · lightfield_opportunities (labels) |
hubspot_deal_id une con la historia de HubSpot |
stg_hubspot__funnel_deals · int_funnel_deals_adela / _qp · fct_funnel_* |
lightfield_opportunities filtrando pipeline_label |
stage_order es la posición dentro del pipeline |
hs_v2_date_entered_* en deals |
stg_lightfield_opportunity_hubspot_stage_dates |
Foto de la migración; ver limitaciones |
hubspot.deal_pipelines · int_pipeline_stages |
stg_lightfield_select_options (field_key = $pipeline / $stage) |
Los ids cambian (pd_…, opt_…); parent_option_id = pipeline |
hubspot.company · stg_hubspot__company · int_hubspot_company |
stg_lightfield_accounts |
hubspot_company_id une con HubSpot; rfc ya normalizado |
hubspot.deal_company · stg_hubspot__deals_company |
account_id en las tablas de oportunidades |
Una cuenta por oportunidad |
hubspot.owners |
stg_lightfield_members |
|
hubspot.contact · stg_hubspot__contacts |
— (RAW solvento-data-prod.lightfield.contacts) |
Sin modelo dbt todavía |
company_property_history · deal_property_history |
— | El historial de campos de Lightfield no se replica |
La clasificación new / cli / renewal de int_hubspot_deals no se traslada sola
Se arma con ids de etapa de HubSpot. En Lightfield los ids son otros, así que hay que redefinirla por pipeline y etapa. cli corresponde al pipeline Customer Request (318 de 453 deals migrados) y renewal a Renovaciones (227 deals, ninguno migrado: el pipeline existe en Lightfield pero sin oportunidades).
Cobertura de la migración
Medido el 2026-10-05: 2.917 de 13.109 deals de HubSpot están en Lightfield, todos con hubspot_deal_id. Lo no migrado sigue disponible solo en hubspot.*.
| Pipeline en HubSpot | Deals en HubSpot | Migrados | % |
|---|---|---|---|
| Adela | 9.424 | 749 | 7,9 % |
| QuickPay / Working Capital | 1.652 | 1.623 | 98,2 % |
| Customer Success 2 | 501 | 0 | 0 % |
| Customer Request | 455 | 319 | 70,1 % |
| Renovaciones | 254 | 0 | 0 % |
| SAAS Pipeline | 203 | 0 | 0 % |
| Carriers factoring | 181 | 168 | 92,8 % |
| Nuevas condiciones | 73 | 0 | 0 % |
| Brokers & Partners | 65 | 0 | 0 % |
| Brokers | 64 | 58 | 90,6 % |
| Otros (Partnerships, Solvento Paga Collab, pipelines sin nombre) | 237 | 0 | 0 % |
Lightfield tiene 12 pipelines; hoy solo 5 tienen oportunidades (Adela, QuickPay / Working Capital, Customer Request, Carriers factoring y Brokers).
Limitaciones que hay que conocer
- Los borrados no se propagan. La key no tiene acceso a la papelera (
status=trashedda 403), así que un registro borrado en Lightfield sigue en la tabla deduplicada. Opciones: un Refresh periódico con remoción de registros, o detectarlos comparando contra un recorrido completo. - Las listas inversas de una cuenta pueden quedar desactualizadas. Vincular una oportunidad no siempre cambia el
updatedAtde la cuenta, y si no cambia el incremental no la vuelve a traer. Tras la carga del 2026-10-04, 31 de las 2.486 cuentas con oportunidades quedaron con la lista$opportunityincompleta (34 oportunidades). Lo mismo puede pasar con$contact,$maily$meeting. Por eso los modelos usan el vínculo del lado del hijo (account_idde la oportunidad) y no cuentan oportunidades desde la cuenta. Un Refresh conservando registros deaccountsycontactscorrige las listas. - No hay fechas de cambio de etapa después del corte.
entered_current_stage_atystg_lightfield_opportunity_hubspot_stage_datesson campos importados de HubSpot: Lightfield no los actualiza cuando una oportunidad cambia de etapa. La historia de etapas de Lightfield existe en el endpoint/opportunities/{id}/fields/{key}/history, pero es una llamada por oportunidad y no se replica. Afecta cualquier funnel por fecha de entrada a etapa. - Los selects dependen de
definitions. Si se crea un pipeline o etapa nueva, el label aparece en la siguiente sync. Los testsnot_nulldepipeline_labelystage_labelavisan (warn) si falta. - Ruido en cuentas. ~7.100 cuentas creadas el 2026-10-04 no vienen de HubSpot ni tienen actividad capturada (todas con owner). Filtrar con
is_from_hubspot/has_captured_activityy revisar su origen con Comercial antes de usarlas. - Frescura. El RAW tiene hasta ~6 h de atraso; las tablas de
adv-analyticsdependen del job diario de dbt-etls (hasta ~1 día). Para más frecuencia, un job de dbt Cloud condbt build --select tag:lightfield. - El destino de BigQuery descarta columnas no declaradas en el esquema del stream (por eso
membersllegó sinfieldsen la v1 del conector). Dentro defieldsyrelationshipsno aplica: ahí entra todo.
Si falla 🛠️
Impacto: 🟢 bajo mientras nadie lea en producción. Cuando crédito migre: los procesos que usan el CRM quedan con datos del día anterior; no bloquea operación ni producto.
| Síntoma | Dónde mirar | Acción |
|---|---|---|
lightfield.* no se actualiza |
UI de Airbyte → conexión de Lightfield (estado y hora del último sync) | Revisar logs y reintentar el sync |
401 / 403 |
Secret Manager lightfield_api_key y la key en Lightfield (Settings → API keys) |
Regenerar la key, actualizar el secreto y la configuración del conector |
400 "Unknown filter field" o limit_too_large |
Manifest del conector | El filtro necesita el $ ($updatedAt[greaterThan]); limit ≤ 25 |
429 |
Logs del sync | El conector reintenta con Retry-After; si persiste, bajar la frecuencia |
pipeline_label / stage_label en NULL (test en warn) |
solvento-data-prod.lightfield.definitions |
Correr la sync (definitions es full refresh); suele ser un pipeline o etapa nuevos |
owner_name en NULL |
solvento-data-prod.lightfield.members |
Correr la sync o refrescar el stream members |
adv-analytics.lightfield.* vieja con el RAW al día |
Job de dbt Cloud de dbt-etls | Re-ejecutar dbt build --select tag:lightfield |
| Un registro borrado en Lightfield sigue en BigQuery | — | Limitación conocida (ver arriba) |
Escalación: conector de Airbyte y dbt-etls → Martin · consumo en crédito y analytics (dbt-analytics, Metabase) → Diego · configuración del CRM (campos, pipelines, cargas) → administración de Lightfield en Comercial.
Enlaces
- 📊 Estado en vivo: dashboard "Data Processes" (Cloud Monitoring)
- ⚙️ Ingesta: Airbyte → conexión de Lightfield (conector custom del Connector Builder); manifest en
lightfield-airbyte(pendiente de subir a GitLab) - 🧮 Lógica:
dbt-etls—models/advanced_analytics/lightfield/ - 🔗 Relacionado: Airbyte · Hubspot (historia previa al corte) · Capa dbt
Última actualización: 2026-10-05 · Pendientes: subir el manifest a GitLab; definir la frecuencia de dbt para tag:lightfield; borrados; historial de etapas posterior al corte. Si cambia el flujo o un modelo dbt, actualizar esta ficha en el mismo MR.