Guía de Integración de ReactiveCRM
Documentación técnica para empresas (inquilinos) que desean crear su propia integración con ReactiveCRM: ingesta de leads y clientes, creación de negocios, envío de eventos de marketing y exportación de datos.
Este documento cubre únicamente las API más utilizadas para integraciones externas. Los datos de referencia internos y los endpoints de servicios de administración quedan intencionalmente fuera del alcance.
1. Descripción general de la integración
Un flujo de integración típico se ve así:
Su sistema (backend / proxy del lado del servidor)
|
| 1. POST /api/auth/login (obtener tokens de acceso + actualización)
v
ReactiveCRM
| 2. Referencias: GET /api/users/paged, GET /api/statuses, GET /api/stages, GET /api/lead-sources
| (obtener UUIDs para ownerId, authorId, statusId, etc.)
v
| 3. Operaciones principales:
| POST /api/leads/create — crear un lead
| POST /api/clients/create — crear un cliente
| POST /api/contacts/create — crear un contacto
| POST /api/deals/create — crear un negocio
| POST /api/dashboard/marketing/events — enviar un evento de marketing
| POST /api/leads/import/batch — importación masiva de leads
v
| 4. Lectura / exportación:
| GET /api/leads/paged — lectura paginada con filtros
| GET /api/export/leads — exportación NDJSON de todos los leads
Regla de seguridad clave: nunca llame a la API del CRM directamente desde el navegador de un usuario final. Mantenga el token del CRM y los identificadores internos en su backend (o en una función serverless).
2. Autenticación
2.1. Obtención de tokens
Los endpoints de autenticación no requieren un token:
| Método | URL | Descripción |
|---|---|---|
POST | /api/auth/login | Inicio de sesión con usuario + contraseña, devuelve tokens de acceso y actualización |
POST | /api/auth/refresh | Intercambiar un token de actualización por un nuevo par de tokens |
POST | /api/auth/logout | Revocar un token de actualización |
curl -X POST "$CRM_BASE_URL/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"username": "integration", "password": "secret123"}'
{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"refreshToken": "a8f3k2m9Qx7Tt1Vv...",
"tokenType": "Bearer",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"firstName": "Integración",
"lastName": "Bot",
"tenantId": "660e8400-e29b-41d4-a716-446655440001"
},
"tenant": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Zunga Corp"
}
}
2.2. Reglas de manejo de tokens
- Token de acceso (
token) — un JWT que tiene una validez de 1 hora. Envíelo con cada solicitud:Authorization: Bearer <token>. - Token de actualización (
refreshToken) — una cadena aleatoria que tiene una validez de 7 días. Úselo para obtener un nuevo par de tokens. - En cada
/api/auth/refresh, el servidor rota el token de actualización: el antiguo se elimina y se emite uno nuevo. Persista ambos nuevos valores. - Una solicitud con un token de acceso caducado devuelve
401. En ese caso, actualice y reintente la solicitud original — no vuelva a iniciar sesión.
2.3. Configuración base
CRM_BASE_URL=https://crm.example.com
Todos los ejemplos a continuación asumen los encabezados:
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json
3. Convenciones de API paginada
Todos los endpoints de listado de la forma GET /api/*/paged comparten las mismas convenciones:
| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
page | entero | 0 | Número de página, basado en cero |
size | entero | por endpoint | Tamaño de página |
sort | cadena | createdAt,desc | Ordenamiento en formato campo,dirección. Dirección: asc o desc |
Estructura de respuesta paginada
{
"content": [ { "..." } ],
"page": 0,
"size": 20,
"totalElements": 137,
"totalPages": 7
}
Filtrado por fecha
Use los parámetros campoDesde / campoHasta para rangos (ISO 8601):
createdAtFrom=2026-01-01T00:00:00Z
createdAtTo=2026-01-31T23:59:59Z
Ordenamiento
Siempre ?sort=campo,dirección:
?sort=createdAt,desc
?sort=name,asc
Algunos campos de filtro tienen parámetros de rango dedicados (p. ej.,
dealAmountFrom/dealAmountTo).
Semántica de filtrado
- Todo el filtrado y ordenamiento se realiza del lado del servidor (no es necesario descargar todo y filtrar del lado del cliente).
- Los múltiples filtros se combinan con AND.
- Los filtros de texto (subcadena) utilizan búsqueda sin distinción entre mayúsculas y minúsculas (ILIKE).
- El filtro universal
searchbusca en múltiples campos con OR.
4. Referencias (obtención de UUIDs)
Antes de crear entidades, obtenga los UUIDs de los datos de referencia relacionados. Los principales son:
4.1. Usuarios (GET /api/users/paged)
Se utiliza para ownerId, authorId, developingManagerIds.
curl "$CRM_BASE_URL/api/users/paged?page=0&size=50&sort=createdAt,asc" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
Ejemplo de respuesta (fragmento de content):
[
{
"id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"firstName": "Roman",
"lastName": "Posledovskiy",
"username": "roman",
"email": "roman@example.com",
"tenantId": "660e8400-e29b-41d4-a716-446655440001"
}
]
4.2. Estados (GET /api/statuses)
Se utiliza para statusId de leads, negocios y clientes de partes de negocios. Devuelve un array:
curl "$CRM_BASE_URL/api/statuses" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "New",
"entityType": "LEAD"
},
{
"id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"name": "In progress",
"entityType": "STAGE"
}
]
4.3. Etapas (GET /api/stages)
Se utiliza para el stageId de un negocio:
curl "$CRM_BASE_URL/api/stages" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
4.4. Fuentes de leads (GET /api/lead-sources)
Devuelve un árbol de fuentes de leads. Se utiliza para el leadSourceId de un lead:
curl "$CRM_BASE_URL/api/lead-sources" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
[
{
"id": "cccc0001-0000-0000-0000-000000000001",
"name": "Website",
"children": [
{
"id": "cccc0001-0000-0000-0000-000000000002",
"name": "Feedback form",
"children": []
}
]
}
]
5. Leads
5.1. Crear un lead (POST /api/leads/create)
curl -X POST "$CRM_BASE_URL/api/leads/create" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "Consulta desde el sitio web: asesoría",
"ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"leadSourceId": "cccc0001-0000-0000-0000-000000000002",
"statusId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"quality": "WARM"
}'
Campos de la solicitud:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
message | cadena | no | Mensaje / texto de la consulta |
ownerId | uuid | sí | Usuario responsable |
authorId | uuid | sí | Usuario que creó el lead |
clientId | uuid | no | Cliente relacionado |
contactId | uuid | no | Contacto relacionado |
leadSourceId | uuid | no | Nodo del árbol de fuentes de leads |
statusId | uuid | no | Estado |
quality | enum | no | HOT, WARM, COOL, COLD |
Ejemplo de respuesta 201 Created:
{
"id": "22222222-2222-2222-2222-222222222222",
"message": "Consulta desde el sitio web: asesoría",
"status": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "New"
},
"quality": "WARM",
"dealId": null,
"createdAt": "2026-09-05T20:00:00Z",
"updatedAt": "2026-09-05T20:00:00Z",
"version": 0,
"author": {
"id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"firstName": "Roman",
"lastName": "Posledovskiy"
},
"owner": {
"id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"firstName": "Roman",
"lastName": "Posledovskiy"
}
}
Guarde el
iddevuelto — es necesario para elleadIddel evento de marketing (consulte la sección 8).
5.2. Lectura paginada (GET /api/leads/paged)
curl "$CRM_BASE_URL/api/leads/paged?page=0&size=20&createdAtFrom=2026-09-01T00:00:00Z&sort=createdAt,desc" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
Filtros clave:
| Parámetro | Tipo | Modo | Descripción |
|---|---|---|---|
statusId | uuid | exacto | Filtrar por estado |
leadSourceId | uuid | exacto | Filtrar por fuente de lead |
quality | enum | exacto | HOT, WARM, COOL, COLD |
message | cadena | ILIKE | Subcadena en el mensaje |
search | cadena | ILIKE (OR) | Buscar en mensaje, contacto, correo, teléfono |
contactEmail | cadena | ILIKE | Por correo del contacto |
contactPhone | cadena | ILIKE | Por teléfono del contacto |
company | cadena | ILIKE | Por nombre de empresa |
clientId | uuid | exacto | Por ID de cliente |
createdAtFrom / createdAtTo | fecha-hora | rango | Por fecha de creación |
updatedAtFrom / updatedAtTo | fecha-hora | rango | Por fecha de actualización |
createdBy | uuid | exacto | Por autor del lead |
También hay filtros para el negocio relacionado: dealStatusId, dealStageId, dealAmountFrom/dealAmountTo, dealProbabilityFrom/dealProbabilityTo.
Ordenamiento: createdAt, updatedAt, message, quality, estado/fuente y otros (formato campo,dirección).
5.3. Obtener un lead individual (GET /api/leads/{id})
curl "$CRM_BASE_URL/api/leads/$LEAD_ID" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
5.4. Importación masiva de leads (POST /api/leads/import/batch)
Para la ingesta masiva de un gran número de leads, use el endpoint de lote. Acepta un array de leads, crea un registro de historial de importación y permite revertir toda la importación.
curl -X POST "$CRM_BASE_URL/api/leads/import/batch" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"fileName": "leads-2026-09-05.csv",
"leads": [
{
"message": "Consulta #1",
"ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"quality": "WARM"
},
{
"message": "Consulta #2",
"ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"quality": "COOL"
}
]
}'
Ejemplo de respuesta:
{
"importId": "44444444-4444-4444-4444-444444444444",
"imported": 2,
"total": 2,
"skipped": []
}
imported— cuántos se crearon.skipped— array de filas omitidas conindex(basado en 0) yreason.
Historial y reversión:
# Historial de importación
curl "$CRM_BASE_URL/api/leads/import/history" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
# Revertir una importación
curl -X POST "$CRM_BASE_URL/api/leads/import/rollback/$IMPORT_ID" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
5.5. Lead rápido desde el sitio web (POST /api/site/leads)
Para formularios del sitio web, existe un único endpoint combinado que crea atómicamente el contacto, su teléfono principal y correo electrónico, el lead, el enlace contacto-lead y el evento de marketing en una sola solicitud — con idempotencia mediante externalId.
Consulte la guía dedicada: site-lead-multi-contract.md.
6. Clientes y Contactos
6.1. Crear un cliente (POST /api/clients/create)
curl -X POST "$CRM_BASE_URL/api/clients/create" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "COMPANY",
"name": "Romashka LLC",
"taxId": "7700000001",
"regNumber": "1234567890",
"country": "RU",
"phone": "+7-495-000-00-01",
"email": "info@romashka.ru",
"website": "https://romashka.ru",
"ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
}'
Campos clave:
| Campo | Tipo | Aplica a | Descripción |
|---|---|---|---|
type | enum | todos | INDIVIDUAL o COMPANY (requerido) |
name | cadena | todos | Nombre para mostrar (requerido) |
firstName / lastName | cadena | INDIVIDUAL | Nombre/apellido |
taxId | cadena | COMPANY | ID fiscal (INN) |
regNumber | cadena | COMPANY | Número de registro |
legalAddress | cadena | COMPANY | Dirección legal |
phone / email / website | cadena | todos | Contactos |
country | cadena | todos | Código de país ISO |
ownerId | uuid | todos | Usuario responsable |
authorId | uuid | todos | Autor |
developingManagerIds | uuid[] | todos | Gerentes de desarrollo |
6.2. Lectura paginada de clientes (GET /api/clients/paged)
curl "$CRM_BASE_URL/api/clients/paged?page=0&size=20&type=COMPANY&search=Romashka&sort=name,asc" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
Filtros clave: name, type (INDIVIDUAL/COMPANY), country, taxId, email, phone, lastName (personas), search (por nombre/ID fiscal/teléfono), createdAtFrom/createdAtTo, createdBy, developingManagerId.
6.3. Verificación de duplicados (GET /api/clients/duplicates)
Antes de crear un cliente, verifique si ya existe uno similar:
# Por ID fiscal y nombre
curl "$CRM_BASE_URL/api/clients/duplicates?type=COMPANY&taxId=7700000001&name=Romashka" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
6.4. Crear un contacto (POST /api/contacts/create)
curl -X POST "$CRM_BASE_URL/api/contacts/create" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Ivan",
"lastName": "Petrov",
"dateOfBirth": "1990-05-15",
"gender": "MALE",
"countryCode": "RU",
"ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
}'
Campos: firstName (requerido), lastName, patronymicName, dateOfBirth (date), gender (MALE/FEMALE), countryCode, ownerId, authorId.
6.5. Lectura paginada de contactos (GET /api/contacts/paged)
curl "$CRM_BASE_URL/api/contacts/paged?page=0&size=20&search=Petrov&sort=createdAt,desc" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
7. Negocios
7.1. Crear un negocio (POST /api/deals/create)
curl -X POST "$CRM_BASE_URL/api/deals/create" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Entrega de hardware de servidor",
"clientId": "9f128931-69fd-493a-9a08-be5be0e6603d",
"statusId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"stageId": "dddd0001-0000-0000-0000-000000000001",
"probability": 60,
"amount": 150000.00,
"ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
"authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
}'
Campos clave:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | cadena | sí | Nombre del negocio |
clientId | uuid | sí | ID del cliente |
statusId | uuid | no | Estado (estado de etapa) |
stageId | uuid | no | Etapa de ventas |
probability | entero | no | Probabilidad 0-100 |
amount | número | no | Monto |
plannedAmount | número | no | Monto planificado |
discountPercent | entero | no | Descuento 0-100 |
startDate / expectedCloseDate | fecha-hora | no | Fechas |
ownerId | uuid | no | Propietario |
leadId | uuid | no | Lead relacionado |
contactId | uuid | no | Contacto relacionado |
productIds | uuid[] | no | Productos (formato simplificado) |
dealProducts | array | no | Líneas de negocio (formato completo) |
dealParties | array | no | Partes del negocio |
7.2. Lectura paginada de negocios (GET /api/deals/paged)
curl "$CRM_BASE_URL/api/deals/paged?page=0&size=20&stageKind=OPEN&sort=createdAt,desc" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
Filtros clave: name (ILIKE), clientId, clientName, statusId, stageId, stageKind (OPEN/WON/LOST), ownerId, search, startDateFrom/startDateTo, expectedCloseDateFrom/expectedCloseDateTo, actualCloseDateFrom/actualCloseDateTo, createdAtFrom/createdAtTo.
8. Eventos de Marketing (Atribución)
Para enviar etiquetas UTM, identificadores de anuncios y fuentes de tráfico, use:
POST /api/dashboard/marketing/events
curl -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"eventType": "lead_submitted",
"occurredAt": "2026-09-05T20:00:00Z",
"visitorId": "visitor-8b7f",
"sessionId": "session-31ac",
"leadId": "22222222-2222-2222-2222-222222222222",
"externalId": "site-form-submit-20260905-000123",
"source": "website",
"channel": "paid",
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "summer-consulting",
"utmContent": "banner-a",
"utmTerm": "crm consultation",
"gclid": "EAIaIQobChMI-example",
"landingUrl": "https://www.example.com/consultation",
"referrer": "https://www.google.com/",
"metadata": {
"formName": "consultation",
"pageType": "landing"
}
}'
Ejemplo de respuesta:
{
"accepted": true,
"duplicate": false,
"eventId": "33333333-3333-3333-3333-333333333333"
}
Reglas:
- Construya un
externalIdestable (UUID o un requestId único). Reenviar con el mismoexternalIdpara la mismasource/inquilino devuelveduplicate: true— eso no es un error. - No genere un nuevo
externalIdal reintentar. - No ponga información de identificación personal (correo, teléfono, nombre, texto del mensaje) en
metadata. Solo atributos técnicos como el nombre del formulario o el tipo de página.
Para más detalles, consulte site-leads-integration-guide.md.
9. Exportación de datos (NDJSON)
Los endpoints de exportación devuelven todos los registros del inquilino en formato NDJSON (un objeto JSON por línea, separados por \n).
| Endpoint | Descripción |
|---|---|
GET /api/export/leads | Todos los leads del inquilino |
GET /api/export/clients | Todos los clientes del inquilino |
GET /api/export/contacts | Todos los contactos del inquilino |
curl "$CRM_BASE_URL/api/export/leads" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
Ejemplo de respuesta (flujo de líneas):
{"id":"550e8400-e29b-41d4-a716-446655440001","message":"Consulta desde el sitio web","quality":"WARM","statusName":"New","createdAt":"2026-08-20T10:00:00+03:00","ownerName":"Ivan Ivanov","clientName":"Romashka LLC","contactFirstName":"Petr","contactLastName":"Petrov","leadSourceName":"Paid search"}
{"id":"550e8400-e29b-41d4-a716-446655440002","message":"Llamada telefónica","quality":"COOL","statusName":"In progress","createdAt":"2026-08-19T09:00:00+03:00","ownerName":"Maria Smirnova","clientName":null}
Importante: NDJSON no es un array JSON válido. Lea la respuesta línea por línea a través de ReadableStream (no llame a JSON.parse() en toda la respuesta).
10. Ejemplo de integración de extremo a extremo
El siguiente escenario crea un lead desde el sitio web, vincula un contacto y un cliente, crea un negocio y envía un evento de marketing.
CRM_BASE_URL=https://crm.example.com
CRM_TOKEN="<access-token>"
# 1. Iniciar sesión
curl -s -X POST "$CRM_BASE_URL/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"username": "integration", "password": "secret123"}' | tee /tmp/login.json
CRM_TOKEN=$(jq -r '.token' /tmp/login.json)
OWNER_ID=$(curl -s "$CRM_BASE_URL/api/users/paged?page=0&size=50" \
-H "Authorization: Bearer $CRM_TOKEN" | jq -r '.content[0].id')
# 2. Crear un cliente
curl -s -X POST "$CRM_BASE_URL/api/clients/create" \
-H "Authorization: Bearer $CRM_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"type\": \"COMPANY\",
\"name\": \"Romashka LLC\",
\"taxId\": \"7700000001\",
\"country\": \"RU\",
\"ownerId\": \"$OWNER_ID\",
\"authorId\": \"$OWNER_ID\"
}" | tee /tmp/client.json
CLIENT_ID=$(jq -r '.id' /tmp/client.json)
# 3. Crear un contacto
curl -s -X POST "$CRM_BASE_URL/api/contacts/create" \
-H "Authorization: Bearer $CRM_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"firstName\": \"Ivan\",
\"lastName\": \"Petrov\",
\"countryCode\": \"RU\",
\"ownerId\": \"$OWNER_ID\",
\"authorId\": \"$OWNER_ID\"
}" | tee /tmp/contact.json
CONTACT_ID=$(jq -r '.id' /tmp/contact.json)
# 4. Crear un lead
curl -s -X POST "$CRM_BASE_URL/api/leads/create" \
-H "Authorization: Bearer $CRM_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"message\": \"Consulta desde el sitio web\",
\"clientId\": \"$CLIENT_ID\",
\"contactId\": \"$CONTACT_ID\",
\"ownerId\": \"$OWNER_ID\",
\"authorId\": \"$OWNER_ID\",
\"quality\": \"WARM\"
}" | tee /tmp/lead.json
LEAD_ID=$(jq -r '.id' /tmp/lead.json)
# 5. Crear un negocio vinculado al lead
curl -s -X POST "$CRM_BASE_URL/api/deals/create" \
-H "Authorization: Bearer $CRM_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"Asesoría para Ivan Petrov\",
\"clientId\": \"$CLIENT_ID\",
\"leadId\": \"$LEAD_ID\",
\"contactId\": \"$CONTACT_ID\",
\"amount\": 50000.00,
\"ownerId\": \"$OWNER_ID\",
\"authorId\": \"$OWNER_ID\"
}"
# 6. Enviar un evento de marketing
curl -s -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
-H "Authorization: Bearer $CRM_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"eventType\": \"lead_submitted\",
\"occurredAt\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
\"leadId\": \"$LEAD_ID\",
\"externalId\": \"request-$(uuidgen)\",
\"source\": \"website\",
\"channel\": \"direct\",
\"landingUrl\": \"https://www.example.com/form\",
\"metadata\": {\"formName\": \"consultation\"}
}"
11. Idempotencia y manejo de errores
- Identificador estable: genere su propio
externalId(UUID o requestId) para cada envío. Reenviar el mismoexternalIdno debe crear un duplicado (para eventos de marketing, el servidor lo maneja —duplicate: true). - Reintentar con el mismo identificador: en caso de error de red, reintente con el mismo
externalId; no genere uno nuevo. - No duplique ciegamente: si una solicitud de creación se agota, primero verifique el resultado (usando su propio requestId o encontrando la entidad creada) en lugar de crear una nueva.
400: carga útil inválida — reintentar sin cambios no ayudará; corrija los datos.401: token de acceso caducado — llame a/api/auth/refreshy reintente la solicitud.403: sin permiso — verifique el rol y el inquilino.5xx/timeout: error transitorio — reintente con el mismoexternalId(para leads, use una cola).
12. Inicio rápido
- Autentíquese mediante
POST /api/auth/login; almacenetokenyrefreshToken. - Agregue
Authorization: Bearer <token>a cada solicitud. Ante401, actualice mediante/api/auth/refresh. - Obtenga referencias (usuarios/estados/etapas/fuentes de leads) una vez y almacene en caché los UUIDs.
- Cree entidades en un orden lógico: cliente → contacto → lead → negocio.
- Use endpoints paginados para lecturas con filtrado y ordenamiento del lado del servidor.
- Para exportaciones, use endpoints NDJSON y lea el flujo línea por línea.
- Para ingesta masiva, use endpoints por lotes (
/api/leads/import/batch,/api/clients/import/batch) con soporte de reversión. - Envíe atribución de marketing mediante
POST /api/dashboard/marketing/eventscon unexternalIdestable. - Nunca almacene ni pase PII en el
metadatadel evento de marketing. - Consulte la documentación detallada por API:
site-leads-integration-guide.md.
Reactive CRM