Skip to content

Búsqueda Global

http
GET /search

Busca en todas las entidades del workspace con una sola solicitud. Retorna resultados agrupados por tipo de entidad — contactos, empresas, negocios, actividades, productos — ordenados por relevancia.

El motor de búsqueda usa índices tsvector de PostgreSQL (GIN) para búsqueda de texto completo, con fallback automático a ILIKE para garantizar resultados incluso con términos parciales o sin coincidencia exacta.

Autenticación

Requiere header Authorization: Bearer {token}. Ver .

Sin permiso especial

Cualquier API key válida puede usar la búsqueda global. No se requiere un permiso adicional más allá de una autenticación exitosa. Los resultados se filtran automáticamente según los módulos activos del workspace.

Parámetros de consulta

ParámetroTipoRequeridoDescripción
qstringTérmino de búsqueda. Mín: 1 carácter, máx: 200 caracteres
typesstringNoTipos de entidad a buscar, separados por coma. Valores posibles: contact, company, deal, activity, product. Default: todos los tipos activos del workspace
limitintegerNoMáximo de resultados por tipo de entidad. Mín: 1, máx: 20. Default: 5

Filtra por tipo para búsquedas más rápidas

Si sabes qué tipo de entidad buscas, usa el parámetro types para limitar la búsqueda. Esto reduce el tiempo de respuesta al evitar consultas innecesarias en tipos que no necesitas.

GET /search?q=juan&types=contact,company

Ejemplos

Búsqueda general

bash
curl -X GET "https://api-crm.zelta.dev/public/v1/search?q=Juan+P%C3%A9rez&limit=5" \
  -H "Authorization: Bearer tu-api-token-aqui"

Ejemplo JS

javascript
const params = new URLSearchParams({
  q: 'Juan Pérez',
  limit: '5'
});

const response = await fetch(
  `https://api-crm.zelta.dev/public/v1/search?${params}`,
  {
    headers: {
      'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`
    }
  }
);

const result = await response.json();

// Itera sobre los grupos de resultados
for (const group of result.data.groups) {
  console.log(`${group.label}: ${group.total} resultado(s)`);
  for (const item of group.results) {
    console.log(`  - ${item.title} (${item.id})`);
  }
}

Ejemplo Py

python
import requests

response = requests.get(
    'https://api-crm.zelta.dev/public/v1/search',
    params={
        'q': 'Juan Pérez',
        'limit': 5
    },
    headers={
        'Authorization': 'Bearer tu-api-token-aqui'
    }
)

result = response.json()

for group in result['data']['groups']:
    print(f"{group['label']}: {group['total']} resultado(s)")
    for item in group['results']:
        print(f"  - {item['title']} ({item['id']})")

Búsqueda filtrada por tipo

bash
curl -X GET "https://api-crm.zelta.dev/public/v1/search?q=Acme&types=company,deal&limit=10" \
  -H "Authorization: Bearer tu-api-token-aqui"

Ejemplo JS

javascript
const params = new URLSearchParams({
  q: 'Acme',
  types: 'company,deal',
  limit: '10'
});

const response = await fetch(
  `https://api-crm.zelta.dev/public/v1/search?${params}`,
  {
    headers: {
      'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`
    }
  }
);

const result = await response.json();
const companies = result.data.groups.find(g => g.entityType === 'company');
console.log('Empresas encontradas:', companies?.total ?? 0);

Ejemplo Py

python
import requests

response = requests.get(
    'https://api-crm.zelta.dev/public/v1/search',
    params={
        'q': 'Acme',
        'types': 'company,deal',
        'limit': 10
    },
    headers={
        'Authorization': 'Bearer tu-api-token-aqui'
    }
)

result = response.json()
groups = result['data']['groups']
companies = next((g for g in groups if g['entityType'] == 'company'), None)
print('Empresas encontradas:', companies['total'] if companies else 0)

Respuesta exitosa

HTTP 200 OK

json
{
  "data": {
    "query": "Juan",
    "totalResults": 3,
    "groups": [
      {
        "entityType": "contact",
        "label": "Contactos",
        "results": [
          {
            "id": "V1StGXR8_Z5jdHi6B-myT",
            "entityType": "contact",
            "title": "Juan Pérez",
            "subtitle": "[email protected]",
            "metadata": {
              "email": "[email protected]",
              "phone": "+507 6123-4567"
            }
          },
          {
            "id": "aB3kLmNpQrSt",
            "entityType": "contact",
            "title": "Juan Carlos Rodríguez",
            "subtitle": "[email protected]",
            "metadata": {
              "email": "[email protected]",
              "phone": null
            }
          }
        ],
        "total": 2
      },
      {
        "entityType": "deal",
        "label": "Negocios",
        "results": [
          {
            "id": "xY9wVuTsRqPo",
            "entityType": "deal",
            "title": "Propuesta Juan Pérez — Licencias Enterprise",
            "subtitle": "$12,500.00",
            "metadata": {
              "value": "12500.00",
              "currency": "USD",
              "status": "open"
            }
          }
        ],
        "total": 1
      }
    ]
  }
}

Campos de la respuesta

Objeto raíz data

CampoTipoDescripción
querystringEl término de búsqueda enviado en el parámetro q
totalResultsintegerTotal de resultados encontrados en todos los tipos combinados
groupsarrayArray de grupos, uno por tipo de entidad con resultados

Objeto en data.groups[]

CampoTipoDescripción
entityTypestringTipo de entidad del grupo: contact, company, deal, activity, product
labelstringEtiqueta en español del grupo (ej: "Contactos", "Empresas", "Negocios")
resultsarrayArray de resultados para este tipo. Puede estar vacío si no hay coincidencias
totalintegerTotal de resultados para este tipo (puede superar el limit — indica cuántos existen en total)

Objeto en data.groups[].results[]

CampoTipoDescripción
idstringIdentificador único de la entidad (nanoid)
entityTypestringTipo de entidad del resultado
titlestringTexto principal del resultado. Para contactos: nombre completo. Para empresas: razón social. Para negocios: título del negocio. Para actividades: título. Para productos: nombre
subtitlestring | nullTexto secundario de apoyo. Para contactos: email. Para empresas: sitio web o email. Para negocios: valor formateado. Para actividades: tipo y fecha de vencimiento. Para productos: SKU o categoría
metadataobjectCampos adicionales específicos del tipo de entidad. Útil para mostrar información complementaria sin hacer una solicitud extra

Contenido de metadata por tipo

  • contact: email, phone
  • company: email, website
  • deal: value, currency, status
  • activity: type, status, dueDate
  • product: type, status, basePrice, currency

Comportamiento del motor de búsqueda

Full-text search con fallback ILIKE

La búsqueda usa PostgreSQL tsvector con índices GIN para máximo rendimiento. Si no se encuentran resultados con full-text, el sistema automáticamente ejecuta una búsqueda ILIKE como fallback:

  1. Fase 1 — Full-text (tsvector): Busca coincidencias exactas y derivaciones morfológicas. Óptimo para términos completos.
  2. Fase 2 — ILIKE fallback: Si la fase 1 no produce resultados, busca coincidencias parciales con %término%. Útil para búsquedas de prefijo o con errores tipográficos leves.

Módulos y entidades buscables

Solo se busca en entidades de módulos que estén activos en el workspace. Si el módulo de Productos está desactivado, los productos no aparecerán en los resultados aunque se incluya product en types.

TipoMódulo requeridoCampos indexados
contactSiempre activoNombre completo, email, teléfono
companySiempre activoNombre de empresa, email, sitio web
dealSiempre activoTítulo del negocio, notas
activityactivitiesTítulo, descripción
productproductsNombre, SKU, descripción, categoría

Relevancia y ordenamiento

Los resultados dentro de cada grupo se ordenan por relevancia descendente. El puntaje de relevancia toma en cuenta la posición del término en el campo (título tiene más peso que descripción) y la frecuencia de aparición.

Problemas comunes

ErrorCausaSolución
401 UnauthorizedToken ausente, inválido o expiradoVerifica tu API token en Configuración > API Keys
400q requeridoSe omitió el parámetro de búsquedaIncluye ?q=tu-termino en la URL
400q muy largoEl término supera 200 caracteresReduce el término de búsqueda
400types inválidoSe envió un tipo de entidad no reconocidoUsa solo: contact, company, deal, activity, product
400limit fuera de rangoEl limit es menor a 1 o mayor a 20Usa un valor entre 1 y 20
Resultados vacíosNo hay coincidencias o el módulo está inactivoVerifica que el módulo esté activo en Configuración > Módulos y que el término sea correcto

Siguientes pasos

  • — Gestiona los contactos encontrados
  • — Accede al detalle de empresas
  • — Consulta y actualiza negocios del pipeline
  • — Completa o edita actividades encontradas
  • — Actualiza el catálogo de productos

Documentación oficial de Zelta