Sincronizar su sistema con una fuente personalizada
Una fuente personalizada conecta un sistema que no tiene un conector integrado: su wiki, su herramienta de tickets, una base de datos, una exportación de cualquier origen. Su código envía documentos a Sursa, y Sursa los convierte en tarjetas en la colección y las carpetas para las que está configurada la fuente, con la misma búsqueda, las mismas respuestas, la misma verificación y los mismos permisos que las tarjetas de cualquier otra fuente.
A diferencia de escribir tarjetas directamente, una fuente personalizada lleva la cuenta de lo que ha enviado. Al final de una sincronización completa, Sursa archiva todos los documentos que usted no envió, así que las eliminaciones en su sistema llegan a Sursa sin trabajo adicional.
Configurar la fuente
Un administrador crea la fuente en Sursa, en Sources → New source → Custom source (fuentes, fuente nueva, fuente personalizada), y elige:
- la colección y, si lo desea, una carpeta para sus tarjetas;
- el modo de carpetas: todas las tarjetas en la carpeta elegida, o subcarpetas que reproducen el
pathde cada documento; - los permisos: los permisos de la colección o «como en la fuente», en cuyo caso cada documento indica quién puede verlo.
La página de la fuente muestra su ID; los ejemplos usan 42.
Elegir una clave
| Clave | Empieza por | Puede |
|---|---|---|
| Clave de la fuente | kbsrc_ | Escribir documentos en esta fuente y nada más: no puede leer ni buscar. Créela en la página de la fuente, en API keys (claves de API de la fuente). |
Clave de la organización con el ámbito import:write | kb_ | Escribir en cualquier fuente personalizada de la organización y leer su estado. Para crear una fuente y sus claves hace falta el ámbito admin. |
La clave de la fuente es la opción más segura para una sola integración, sobre todo si funciona en una plataforma de
terceros. Una clave de la organización con import:write conviene a un servicio que alimenta varias fuentes.
Las dos claves se envían de la misma manera, y todos los endpoints de envío están en
/v1/push/sources/{source_id}. Compruebe la clave y el estado de la fuente con
GET /v1/push/sources/{source_id}:
curl https://api.sursa.com/v1/push/sources/42 \
-H "Authorization: Bearer $SURSA_SOURCE_KEY"{"source_id": 42, "name": "Helpdesk articles", "documents": 1840, "open_sync": null}
El documento
| Campo | Obligatorio | Descripción |
|---|---|---|
external_id | sí | Su ID estable del documento, de hasta 512 caracteres. Si vuelve a enviar el mismo ID, el documento se sustituye. |
title | sí | Título de la tarjeta, de hasta 500 caracteres. En un archivo, por defecto, el nombre del archivo. |
content | sí, salvo que haya un archivo | Hasta 5 MB. |
content_type | no | html (predeterminado), markdown o text. Del HTML se eliminan los scripts, los estilos, los formularios y los objetos incrustados. |
url | no | Enlace al documento en su sistema, que se muestra en la tarjeta. |
path | no | Carpetas, como un array (["Support", "Billing"]) o una cadena ("Support/Billing"), hasta 10 niveles. |
permissions | no | {"everyone": true} o {"emails": [...], "groups": [...]}. Se usa cuando los permisos de la fuente son «como en la fuente». |
tags | no | Hasta 50 etiquetas, que se añaden a las etiquetas de la fuente. |
author_email | no | Si es un usuario de la organización, pasa a ser el responsable de la tarjeta. |
updated_at | no | Cuándo cambió el documento en su sistema (RFC 3339). |
metadata | no | Sus pares clave-valor en la tarjeta. Consulte Metadatos. |
category | no | Categoría de la tarjeta: la clave de una categoría de la organización. |
verifiers, verify_interval_days | no | Quién verifica la tarjeta (usuarios por correo electrónico y grupos) y con qué frecuencia, en días. |
upload_id | no | El archivo del documento procedente de una subida por partes, en lugar de content. |
attachments | no | Hasta 20 archivos más del documento, como una lista de upload_id. Cada uno se convierte en una tarjeta propia de la fuente. |
En lugar de content, un único documento puede llevar un archivo de hasta 100 MB en una solicitud
multipart/form-data: el archivo en la parte file y los campos anteriores como JSON en la parte document. Las
subidas por partes para upload_id y attachments se crean con una clave de la organización que tenga el ámbito
import:write y la finalidad import_attachment; una clave de fuente no puede crearlas.
Dos formas de enviar
Las actualizaciones directas convienen a los sistemas que le avisan de cada cambio, como un webhook de su herramienta de soporte o un paso en Zapier. Envíe un documento cuando se cree o cambie, y elimínelo cuando se retire:
| Solicitud | Hace |
|---|---|
POST /v1/push/sources/{source_id}/documents | Crea o sustituye un documento. |
POST /v1/push/sources/{source_id}/documents/batch | Crea o sustituye muchos documentos a la vez. |
DELETE /v1/push/sources/{source_id}/documents/{external_id} | Elimina un documento. Codifique el ID para URL. |
Los cambios se convierten en tarjetas en aproximadamente un minuto; varios cambios seguidos se procesan juntos.
Las sincronizaciones convienen a las exportaciones periódicas: usted lo envía todo, o todo lo que ha cambiado, y Sursa concilia. El resto de esta guía trata de las sincronizaciones.
Ejecutar una sincronización completa
Una sincronización tiene tres pasos: abrir, enviar y cerrar.
1. Abrir
POST /v1/push/sources/{source_id}/syncs abre una sincronización y devuelve su
número:
curl -X POST https://api.sursa.com/v1/push/sources/42/syncs \
-H "Authorization: Bearer $SURSA_SOURCE_KEY" \
-H "Idempotency-Key: sync-2026-10-24" \
-H "Content-Type: application/json" \
-d '{"type": "initial", "max_minutes": 180}'{"sync_number": 7, "type": "initial", "status": "open", "opened_at": "2026-10-24T02:00:00Z",
"expires_at": "2026-10-24T05:00:00Z", "pushed": 0, "removed": 0}
typeesinitialen la primera sincronización de la fuente eincrementaluna vez que se ha completado una sincronización. Una sincronizaciónincrementalantes de que se haya completado alguna devuelvesources.push_initial_required.- Solo puede haber una sincronización abierta a la vez: una segunda devuelve
409sources.push_sync_open. - Una sincronización permanece abierta durante
max_minutes(60 por defecto, hasta 1440). Después caduca: no se archiva nada y su número deja de aceptarse. Elija un tiempo holgadamente más largo de lo que tarda su exportación.
2. Enviar documentos
Envíe los documentos en lotes de hasta 500, con el número de la sincronización. El cuerpo de un lote ocupa hasta
50 MiB; los archivos dentro de un lote se pasan como upload_id.
curl -X POST https://api.sursa.com/v1/push/sources/42/documents/batch \
-H "Authorization: Bearer $SURSA_SOURCE_KEY" \
-H "Idempotency-Key: sync-7-batch-1" \
-H "Content-Type: application/json" \
-d '{
"sync_number": 7,
"documents": [
{"external_id": "faq-shipping", "title": "Shipping", "content_type": "markdown",
"content": "# Shipping\n\nWe ship worldwide within 5 days.", "path": ["Support"]},
{"external_id": "faq-refunds", "title": "Refunds", "content_type": "html",
"content": "<p>Refunds take 14 days.</p>", "path": ["Support", "Billing"],
"permissions": {"groups": ["Support"]}, "metadata": {"article_id": "1042"}}
]
}'La respuesta tiene un resultado para cada documento, en el orden en que los envió:
{
"results": [
{"external_id": "faq-shipping", "result": "unchanged", "status": "indexed", "card_id": "8c1d…", "version": "5e0f…"},
{"external_id": "faq-refunds", "result": "updated", "status": "pending", "card_id": "3f2c…", "version": "a91b…"}
]
}
| Campo | Significado |
|---|---|
result | Qué le ha pasado ahora al documento: created, updated, unchanged, deleted, not_found, error o skipped (en un lote atómico que no se aplicó). |
status | En qué punto está el documento en su camino hacia una tarjeta: pending, processing (la tarjeta está escrita y se está indexando), indexed, failed o removed. |
card_id | La tarjeta del documento, una vez que existe. |
version | Un hash del contenido y de los campos. El mismo documento enviado de nuevo tiene la misma versión y queda unchanged. |
error, reason | Por qué falló el documento. reason es un código estable: content_invalid, file_rejected, too_large, limit_reached, index_failed o batch_rejected (falló otro documento de un lote atómico). |
De forma predeterminada, cada documento de un lote se aplica por separado: un documento incorrecto no detiene a los demás.
Los documentos que no han cambiado desde la última sincronización no hace falta volver a enviarlos. Confírmelos por ID
con POST /v1/push/sources/{source_id}/syncs/{sync_number}/touch, hasta
1000 ID por solicitud, para que la conciliación completa los conserve:
curl -X POST https://api.sursa.com/v1/push/sources/42/syncs/7/touch \
-H "Authorization: Bearer $SURSA_SOURCE_KEY" \
-H "Content-Type: application/json" \
-d '{"external_ids": ["faq-contact", "faq-hours"]}'3. Cerrar
POST /v1/push/sources/{source_id}/syncs/{sync_number}/close termina la
sincronización:
curl -X POST https://api.sursa.com/v1/push/sources/42/syncs/7/close \
-H "Authorization: Bearer $SURSA_SOURCE_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "complete"}'status | Efecto |
|---|---|
complete | Conciliación completa. Se archivan todos los documentos de la fuente que no se enviaron ni se confirmaron en esta sincronización. Úselo solo cuando lo haya enviado todo. |
complete_incremental | Aplica lo que envió y no archiva nada. |
failed | No archiva nada y conserva lo que ya se envió. Añada reason (por ejemplo, API_ERROR) y error_details para el registro. |
Cierre con failed siempre que su exportación se detenga a medias: un complete después de una exportación parcial
archivaría todos los documentos a los que no llegó. Repetir el mismo cierre devuelve el mismo resultado.
Después del cierre, Sursa convierte los documentos en tarjetas en aproximadamente un minuto. La página de la fuente
muestra cada sincronización con el número de documentos enviados y archivados, y
GET /v1/push/sources/{source_id}/syncs/{sync_number} devuelve los mismos
contadores.
Sincronizaciones incrementales
Entre sincronizaciones completas, envíe solo lo que ha cambiado:
- Abra con
"type": "incremental". - Envíe los documentos cambiados y ponga en
deleteslos ID de los eliminados (más abajo). - Cierre con
complete_incremental.
Ejecute de vez en cuando una sincronización completa, por ejemplo cada semana, para recoger todo lo que se le haya escapado a una ejecución incremental.
Eliminar documentos en un lote
Un lote puede eliminar documentos a la vez que escribe otros. Enumere sus ID en deletes:
{
"sync_number": 8,
"documents": [{"external_id": "faq-shipping", "title": "Shipping", "content": "…"}],
"deletes": ["faq-old-returns", "faq-fax"]
}
Cada ID eliminado recibe su propia entrada en results, con result igual a deleted, o not_found si la fuente no
tiene ese documento. Volver a eliminar el mismo ID no causa ningún problema.
Lotes atómicos
Algunos cambios solo tienen sentido juntos, por ejemplo un documento y el que lo sustituye. Envíe "atomic": true y
el lote se aplicará por completo o no se aplicará: si algún documento no supera sus comprobaciones, no se aplica nada
del lote, y la respuesta es 422 con el código sources.push_batch_rejected y el resultado de cada documento en
error.details.results: los documentos que fallaron tienen error, y los demás, skipped.
{"sync_number": 8, "atomic": true, "documents": […], "deletes": ["faq-old-returns"]}
Sin atomic, un lote se aplica documento por documento. Use lotes atómicos para cambios relacionados, y lotes
normales para cargas masivas, en las que un documento incorrecto no debe frenar al resto.
Comprobar el resultado de cada documento
La respuesta del lote le indica cómo se escribió cada documento. La conversión en tarjeta ocurre después, así que
status todavía puede ser pending. Para encontrar los documentos de una sincronización que no se convirtieron en
tarjetas:
curl "https://api.sursa.com/v1/push/sources/42/syncs/7/documents?status=failed" \
-H "Authorization: Bearer $SURSA_SOURCE_KEY"Cada entrada tiene external_id, title, status, card_id, version y reason, y la lista se pagina con
cursor. status también acepta pending, processing, indexed y removed.
También puede recibir el aviso en lugar de preguntar: los eventos import.sync_completed (una sincronización se ha
cerrado y procesado, con sus totales) e import.document_failed (un documento no se convirtió en tarjeta, con su
reason) llegan por webhook y al feed de eventos.
Reintentos
- Envíe una
Idempotency-Keycon cadaPOST. Un lote repetido con la misma clave devuelve el primer resultado. - Incluso sin la clave, un documento con el mismo
external_idnunca se convierte en una segunda tarjeta: quedaunchangedoupdated. - Si el proceso se detiene en mitad de una sincronización, abra una nueva cuando caduque la anterior, o cierre la
anterior con
failedsi todavía tiene su número, y vuelva a ejecutar la sincronización.
Límites
| Límite | Valor |
|---|---|
| Contenido de un documento | 5 MB |
| Archivo en una solicitud de un solo documento | 100 MB |
| Documentos por lote | 500 |
| Cuerpo de la solicitud de un lote | 50 MiB |
ID por solicitud touch | 1000 |
| Documentos por fuente | Depende del plan: desde 100.000 |
| Sincronización abierta | 60 minutos por defecto, hasta 24 horas |
Un documento que supera el límite de documentos de la fuente falla con el motivo limit_reached en un lote; una
solicitud de un solo documento responde 409 con el código
sources.push_too_many_documents. Los límites de frecuencia se aplican
como a cualquier otra solicitud; consulte Límites de frecuencia y cuotas.
Errores frecuentes
| Respuesta | Causa | Qué hacer |
|---|---|---|
401 sources.push_key_invalid | La clave es incorrecta, se ha revocado o pertenece a otra fuente. | Compruebe la clave y el ID de la fuente en la ruta. |
400 sources.push_document_invalid | Falta un campo obligatorio o se ha superado un límite. | Corrija el documento; en un lote normal, solo falla ese documento. |
409 sources.push_sync_open | Hay otra sincronización abierta. | Ciérrela o espere a que caduque. |
409 sources.push_sync_closed | La sincronización está cerrada o ha caducado. | Abra una sincronización nueva; aumente max_minutes para las exportaciones largas. |
403 sources.feature_disabled | Las fuentes no forman parte del plan de la organización. | Póngase en contacto con el administrador. |
429 | Demasiadas solicitudes. | Espere lo que indica Retry-After; envíe menos lotes y más grandes. |