Kelova Docs

Fuentes

Indexar, sincronizar y consultar el estado de tus documentos

Una fuente (source) es un documento, sitio web o conector que Kelova indexa como conocimiento consultable. Todos los endpoints de esta página requieren JWT; la creación, edición y borrado requieren rol admin — la lectura acepta admin o member.

Listar fuentes

curl https://api.kelova.app/ingest/sources \
  -H "Authorization: Bearer <token>"
[
  {
    "source_id": "3f2e1a...",
    "name": "Catálogo 2026",
    "source_type": "file",
    "sync_status": "synced",
    "last_synced_at": "2026-07-08T10:15:00Z",
    "created_at": "2026-06-01T09:00:00Z",
    "chunks_count": 214
  }
]

sync_status es uno de: pending (nunca sincronizada), syncing (en curso), synced (última sync exitosa), error (falló — revisa error_message), reauth_required (credenciales OAuth expiradas).

Crear una fuente

Para fuentes sin archivo (web, y conectores en modo referencia) — source_type acepta: file, gdrive, onedrive, notion, web, whatsapp, sap_b1, dynamics, api, audio.

curl -X POST https://api.kelova.app/ingest/sources \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sitio corporativo",
    "source_type": "web",
    "source_url": "https://tuempresa.com"
  }'

Respuesta (201):

{
  "source_id": "3f2e1a...",
  "name": "Sitio corporativo",
  "sync_status": "pending"
}

La fuente queda en pending — dispara el primer sync con POST /ingest/sources/{id}/sync.

Para sitios web, corre POST /ingest/sources/preflight antes de crear la fuente — verifica en segundos si la URL es indexable (no es SPA, no está detrás de Cloudflare, tiene suficiente texto) sin gastar cupo de fuentes. Body: {"source_type": "web", "source_url": "..."}. Respuesta: {"indexable": true, "pages_found": 12, "max_pages": 50, "sample_title": "..."} o {"indexable": false, "error": "..."}.

Subir un archivo

POST /ingest/sources/upload es multipart/form-data, no JSON. Acepta PDF, DOCX, XLSX, PPTX, CSV, TXT, Markdown, imágenes (PNG/JPEG/TIFF/WebP/BMP, vía OCR) y audio (WAV/MP3/OGG/M4A/FLAC/WebM, vía transcripción). Máximo 50 MB (20 MB para imágenes).

curl -X POST https://api.kelova.app/ingest/sources/upload \
  -H "Authorization: Bearer <token>" \
  -F "name=Manual de producto" \
  -F "file=@./manual.pdf"

Respuesta (201) — indexado sincrónicamente, sin necesidad de disparar un sync aparte:

{
  "source_id": "3f2e1a...",
  "name": "Manual de producto",
  "sync_status": "synced",
  "chunks_count": 87
}

Si el chunking o el embedding fallan, la respuesta sigue siendo 201 (la fuente se crea) pero con sync_status: "error" y error_message con la causa — no hace falta pollear /status para saberlo.

La estrategia de chunking (paragraph, section, row) se detecta automáticamente por MIME type — no es configurable.

Sincronizar manualmente

curl -X POST https://api.kelova.app/ingest/sources/{id}/sync \
  -H "Authorization: Bearer <token>"

Respuesta (202) — el sync corre en background:

{
  "source_id": "3f2e1a...",
  "message": "sync started"
}

Responde 409 SYNC_IN_PROGRESS si ya hay un sync activo para esa fuente (salvo que el lock tenga más de 30 minutos, en cuyo caso se considera stale y se sobreescribe). El sync reemplaza todos los chunks de la fuente en una única transacción — nunca deja estados parciales visibles a las queries.

Consultar el estado (polling)

curl https://api.kelova.app/ingest/sources/{id}/status \
  -H "Authorization: Bearer <token>"
{
  "source_id": "3f2e1a...",
  "sync_status": "synced",
  "last_synced_at": "2026-07-10T08:00:00Z",
  "chunks_count": 214
}

Preview de chunks indexados

Devuelve los primeros 3 chunks (contenido truncado a 200 caracteres) — útil para verificar visualmente que el contenido se indexó bien.

curl https://api.kelova.app/ingest/sources/{id}/preview \
  -H "Authorization: Bearer <token>"
[
  {
    "content": "Kelova indexa el conocimiento interno de tu empresa...",
    "chunk_level": "child",
    "location": "1"
  }
]

Historial de syncs

curl "https://api.kelova.app/ingest/sources/{id}/history?limit=20" \
  -H "Authorization: Bearer <token>"
[
  {
    "id": "a1b2c3...",
    "action": "sync_completed",
    "details": { "chunks_written": 214, "provider": "voyage" },
    "created_at": "2026-07-10T08:00:00Z"
  }
]

Sync automático (schedule)

curl -X PUT https://api.kelova.app/ingest/sources/{id}/schedule \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"frequency": "24h"}'

frequency acepta manual, 1h, 6h, 24h, weekly — las frecuencias disponibles dependen del plan (ver Límites de uso). Responde 402 si tu plan no incluye la frecuencia pedida.

{
  "source_id": "3f2e1a...",
  "frequency": "24h",
  "next_sync_at": "2026-07-11T08:00:00Z",
  "enabled": true
}

GET /ingest/sources/{id}/schedule devuelve la misma forma (además de last_sync_at); si nunca se configuró, devuelve {"source_id": "...", "frequency": "manual", "enabled": false}.

Renombrar, reordenar y eliminar

# Renombrar
curl -X PATCH https://api.kelova.app/ingest/sources/{id} \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "Catálogo 2026 — v2"}'

# Reordenar (posición en el listado del dashboard)
curl -X PATCH https://api.kelova.app/ingest/sources/reorder \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '[{"source_id": "3f2e1a...", "position": 0}, {"source_id": "9c8b7a...", "position": 1}]'

# Eliminar
curl -X DELETE https://api.kelova.app/ingest/sources/{id} \
  -H "Authorization: Bearer <token>"

DELETE responde {"status": "deleted"} y borra la fuente junto con todos sus chunks. El archivo original en storage no se elimina — puedes seguir descargándolo (ver abajo) aunque la fuente ya no exista como fila indexada.

Descargar el archivo original

Devuelve una URL firmada (24h) al archivo tal como se subió — solo aplica a fuentes con archivo almacenado (file, audio).

curl https://api.kelova.app/ingest/sources/{id}/download \
  -H "Authorization: Bearer <token>"
{
  "signed_url": "https://.../storage/v1/object/sign/..."
}

Responde 404 SOURCE_NOT_FOUND si la fuente no tiene archivo asociado (fuentes tipo web, o uploads previos a que esta función existiera).


Conectores OAuth (Google Drive, OneDrive) y el conector de WhatsApp para ingesta usan flujos de redirección/verificación adicionales fuera del alcance de esta referencia REST — se configuran desde el dashboard.

On this page