API

Introducción

swagger.png

Todo lo que se puede hacer desde la aplicación web está disponible también a través de la API REST de NUCLEUS, de modo que la anonimización y la generación de datos sintéticos se pueden automatizar desde aplicaciones y procesos propios. La documentación interactiva (Swagger) está en el endpoint /docs de la API.

Autenticación. Cada petición se autoriza con el token personal, que se pasa como parámetro de consulta (?token=SU_TOKEN). La única excepción es el catálogo de métodos, que es público para que una interfaz pueda cargarlo antes de que nadie inicie sesión. Las peticiones tienen límite de frecuencia por cuenta.

Trabajo asíncrono. La anonimización y el entrenamiento no terminan dentro de la petición. Responden de inmediato con un runId, y esa ejecución se sigue con un endpoint de estado. No se pierde nada si el proceso que llamó se cae por el camino: la ejecución continúa y el identificador sigue siendo válido.

Referencia de endpoints

Anonimización

EndpointPara qué sirve
GET /nucleus/anonymization_methodsEl catálogo de métodos, sus parámetros y cuáles se aplican a cada clase de activo. No necesita token.
GET /nucleus/anonymization_methods/resolveQué métodos se admiten para una columna o un elemento sensible concreto, y cuál es el de por defecto.
POST /nucleus/anonymizeAnonimiza uno o varios conjuntos de datos. Cuatro formas de entregar el dato.
GET /nucleus/anonymize/runs/\{run_id\}El estado de una anonimización y qué ha producido.
GET /nucleus/download/anonymized/{run_id}Enlaces de descarga temporales para los conjuntos anonimizados.
POST /nucleus/anonymize/incrementAnonimiza las filas que han llegado después de una entrega, manteniendo las mismas equivalencias.
POST /nucleus/deanonymizeRestaura los valores originales de columnas concretas.

Datos sintéticos

EndpointPara qué sirve
POST /nucleus/synthesizeEntrena un sintetizador.
POST /nucleus/generate/\{run_id\}Genera un conjunto sintético a partir de un sintetizador entrenado.
POST /nucleus/generate/realtime/\{run_id\}Genera una muestra pequeña y devuelve las filas en la propia respuesta.
GET /nucleus/download/syntheticdata/\{run_id\}Descarga un conjunto generado en CSV, PARQUET o JSON.
POST /nucleus/uploadmodelSube un sintetizador entrenado localmente con Nucleus Edge.
GET /nucleus/runs/listLista los sintetizadores entrenados.
GET /nucleus/runs/info/\{run_id\}Detalles y estado de un sintetizador.
GET /nucleus/runs/logs/\{run_id\}Registros de entrenamiento de una ejecución.

Descubrir los métodos

Nunca hace falta dejar la lista de métodos escrita a mano en el código. Se pide el catálogo:

GET /nucleus/anonymization_methods

json

\{

  "version": "2026.08",

  "methods": \{

    "generalize": \{

      "code": "generalize",

      "name_en": "Generalize", "name_es": "Generalizar",

      "description_es": "Sustituye el valor por el rango en el que cae.",

      "param": \{ "name": "bucket", "type": "number", "default": 10, "min": 0.0001 \},

      "enabled": true

    \},

    "hash": \{ "code": "hash", "param": null, "enabled": true \}

  \},

  "rules": \{

    "dataset":  \{ "by_dtype":   \{ "numeric": \{ "allowed": ["generalize", "perturb", "..."], "default": "generalize" \} \} \},

    "image":    \{ "by_element": \{ "face":    \{ "allowed": ["blur", "pixelate", "redact"],   "default": "blur" \} \} \},

    "document": \{ "default_element": \{ "allowed": ["..."], "default": "..." \} \},

    "audio":    \{ "default_element": \{ "allowed": ["beep", "silence", "remove"], "default": "beep" \} \}

  \}

\}

Conviene leer tres cosas de ahí:

  • methods[código].param es el esquema JSON del parámetro extra de ese método: su nombre, su tipo, su valor por defecto y las options admitidas cuando es una lista cerrada. null significa que el método no lleva parámetro.

  • methods[código].enabled dice si el motor puede ejecutarlo de verdad. Un método deshabilitado puede aparecer en la lista para que una interfaz lo muestre como «próximamente», pero no debe enviarse.

  • rules resuelve qué métodos tienen sentido dónde: por tipo de dato de la columna en las tablas, por elemento sensible en las imágenes, y un único valor por defecto para documentos y audio.

Dos parámetros de consulta opcionales acotan la respuesta: asset_type (dataset, image, document, audio) recorta rules a esa clase, y enabled_only=true descarta los métodos que aún no se pueden ejecutar.

Si prefiere no cruzar el catálogo por su cuenta, puede preguntar por una sola columna o un solo elemento y recibir la respuesta ya resuelta:

GET /nucleus/anonymization_methods/resolve?asset_type=dataset&dtype=numeric

GET /nucleus/anonymization_methods/resolve?asset_type=image&element=face

dtype es para tablas (numeric, datetime, string, categorical, boolean); element es para imágenes, documentos y audio, y acepta tanto el código como el nombre visible en español o en inglés.

Escribir la configuración

La configuración es el mismo objeto sea cual sea la forma de enviar los datos. Indica, para cada columna, qué hacer con ella:

json

\{

  "anonymizerName": "Empleados – copia para proveedor",

  "anonymizerDescription": "Anonimizado para el equipo de analítica externo",

  "anonymizerUseCase": "103",

  "datasets": [

    \{

      "datasetName": "empleados",

      "columns": \{

        "id_empleado":      \{ "method": "pseudonym", "param": "EMP-\\d\{6\}" \},

        "nombre":           \{ "method": "simulate", "param": "first_name" \},

        "apellidos":        \{ "method": "simulate", "param": "last_names" \},

        "email":            \{ "method": "simulate", "param": "email",

                              "derive_from": ["nombre", "apellidos"] \},

        "dni":              \{ "method": "mask", "param": "opaque" \},

        "fecha_nacimiento": \{ "method": "date_shift", "param": "id_empleado" \},

        "codigo_postal":    \{ "method": "generalize", "param": 5, "type": "string" \},

        "salario":          \{ "method": "perturb", "param": 0.05 \},

        "notas":            \{ "method": "coding", "param": "surrogates" \}

      \}

    \}

  ]

\}

Campos de la raíz

CampoObligatorioSignificado
anonymizerNameUn nombre para la entrega. Da nombre también a la colección que agrupa los resultados.
anonymizerDescriptionTexto libre, para quien encuentre esta ejecución más adelante.
anonymizerUseCaseCódigo del caso de uso; por ejemplo "103" para compartición externa de datos.
datasetsUna entrada por tabla. Una sola tabla es una lista de un elemento.
basedOnRunIdnoContinúa las equivalencias de una ejecución anterior (véase Añadir filas).
runIdnoPublica un identificador de ejecución propio en lugar de dejar que lo genere la API.

Campos de cada dataset

CampoSignificado
datasetNameEl nombre de la tabla. Es lo que permite casar la configuración con los datos que se envían.
columnsNombre de columna → qué hacer con ella.
assetIdSolo cuando el dato ya está en la plataforma. En los demás casos se omite: se resuelve automáticamente.
rowsLos datos en sí, cuando se envían en línea (solo en JSON).

Campos de cada columna

CampoSignificado
methodEl código del método, del catálogo. El único campo obligatorio.
paramEl parámetro extra del método. Un valor suelto, o un objeto con los parámetros nombrados.
references"tabla.columna". Reutiliza las equivalencias de otra columna, de forma que una clave ajena recibe la misma sustitución que recibió la entidad en su propia tabla.
derive_fromConstruye este valor a partir del valor ya sustituido de otra columna de la misma fila. Admite una lista.
group_variantsActivo por defecto. Las variantes de un mismo valor en una columna comparten sustitución, de modo que Dedomena y Dedomena.AI acaban siendo la misma empresa ficticia. Se pone a false donde valores casi idénticos son de verdad entidades distintas.
typeEl tipo de la columna —numeric, datetime, string, categorical, boolean— cuando no se quiere que se infiera. Es lo que evita que un código postal como 08001 se lea como el número 8001 y pierda el cero, algo que ningún paso posterior puede recuperar.

El parámetro de cada método

MétodoparamNotas
pseudonymel patrón, p. ej. "EMP-\\d\{6\}"Literales, \d, \w, clases como [A-Z0-9] y repeticiones \{n\}. Sin patrón, los identificadores se generan libremente. Dos registros nunca reciben el mismo.
simulateel proveedor, p. ej. "first_name"Genera un valor verosímil en lugar de ruido. email, phone y url salen de rangos reservados, así que un valor generado nunca pertenece a una persona real.
mask"asterisks" u "opaque"Tapa el valor en lugar de sustituirlo.
generalizeel tamaño del rango, p. ej. 5Sustituye el valor por el rango en el que cae.
perturbruido de 0.0 a 1.0Conserva la distribución.
date_shiftla columna por la que mantenerse estableMueve la fecha conservando el mismo intervalo en todas las filas de una misma entidad, de forma que las edades y las secuencias siguen cuadrando.
coding"tokens", "surrogates" o "invented"Texto libre: encuentra los datos personales dentro y los sustituye. surrogates reutiliza la sustitución que esa misma persona recibió en su propia columna.
text_regenerateDescarta el texto original y redacta uno nuevo a partir de los valores ya sustituidos del registro. Para los campos demasiado densos en datos personales para fiarse de la detección.
hash, shuffle, drop
blur, pixelate, redactpixelate admite el tamaño de bloqueImágenes.
beep, silence, removeAudio.

Las columnas que no se declaran se entregan intactas. Es la forma prevista de conservar los campos que no llevan datos personales.

Relacionar varias tablas. Una clave ajena tiene que recibir la misma sustitución que recibió la entidad en su propia tabla, o los datos dejan de cruzarse. Se escribe con references, usando "tabla.columna":

json

\{

  "datasets": [

    \{ "datasetName": "empleados",

      "columns": \{ "id_empleado": \{ "method": "pseudonym", "param": "EMP-\\d\{6\}" \} \} \},

    \{ "datasetName": "ausencias",

      "columns": \{ "id_empleado": \{ "method": "pseudonym",

                                    "references": "empleados.id_empleado" \} \} \}

  ]

\}

Como las referencias se escriben por nombre y no por identificador, la configuración entera se puede redactar antes de haber subido nada.

Enviar los datos: cuatro vías de entrada

POST /nucleus/anonymize?token=SU_TOKEN

La misma ruta admite dos tipos de contenido, y es la propia petición la que dice cuál: con application/json el cuerpo es la configuración y el dato viaja dentro de ella; con multipart/form-data la configuración va en un campo configuration y los conjuntos de datos se adjuntan como ficheros.

Exactamente una de estas cuatro por llamada:

VíaCómoCuándo
rowsEl dato en línea, dentro de cada dataset de un cuerpo JSON.Miles de filas, directamente desde su aplicación.
filesLos conjuntos de datos adjuntos a una petición multipart.Tablas grandes, o ficheros que ya tiene en disco.
collectionId / collection_idEl identificador de una colección que ya está en la plataforma.Datos subidos antes, varias tablas a la vez.
assetId / asset_idEl identificador de un único conjunto ya subido, bien como campo de su dataset en la configuración, bien como parámetro de la llamada.Una sola tabla que ya está en la plataforma.

1 — El dato en el cuerpo (JSON). La forma más cómoda desde un backend: sin multipart, en una sola petición.

json

\{

  "anonymizerName": "Empleados – copia para proveedor",

  "anonymizerDescription": "Anonimizado para el equipo de analítica externo",

  "anonymizerUseCase": "103",

  "dataSource": 232,

  "datasets": [

    \{

      "datasetName": "empleados",

      "columns": \{ "nombre": \{ "method": "simulate", "param": "first_name" \} \},

      "rows": [

        \{ "id_empleado": "EMP-000001", "nombre": "Ana",  "salario": 30000 \},

        \{ "id_empleado": "EMP-000002", "nombre": "Luis", "salario": 41000 \}

      ]

    \}

  ]

\}

bash

curl -X POST "https://\<su-nucleus-api\>/nucleus/anonymize?token=SU_TOKEN" \

     -H "Content-Type: application/json" \

     -d @anonymize_config.json

Lo que en multipart son campos del formulario pasan a ser campos del cuerpo: dataSource (231 dominio público, 232 propio, 233 licenciado) y, si hace falta, country y useCases.

Las filas en línea se sostienen enteras en memoria y viajan en una sola petición, así que esta vía sirve para miles de filas, no para millones. Por encima de eso, adjunte el fichero o súbalo antes.

2 — Los conjuntos adjuntos (multipart). El nombre de cada fichero sin su extensión tiene que coincidir con un datasetName.

bash

curl -X POST "https://\<su-nucleus-api\>/nucleus/anonymize?token=SU_TOKEN" \

     -F "configuration=$(cat anonymize_config.json)" \

     -F "data_source=232" \

     -F "files=@empleados.csv" \

     -F "files=@ausencias.csv"

Formatos admitidos: csv, txt, tsv, json (un array de objetos o JSON Lines), jsonl, parquet, xlsx. El separador se detecta, así que un CSV con punto y coma no necesita ninguna indicación adicional.

3 — Una colección que ya está en la plataforma. No se vuelve a subir nada; cada datasetName se casa con los nombres de los activos de la colección, y un nombre que no casa con ninguno se avisa antes de que la llamada responda.

bash

curl -X POST "https://\<su-nucleus-api\>/nucleus/anonymize?token=SU_TOKEN" \

     -F "configuration=$(cat anonymize_config.json)" \

     -F "collection_id=ID_DE_LA_COLECCION"

4 — Un único conjunto que ya está en la plataforma. O se pone su assetId dentro de su dataset en la configuración, o se pasa asset_id junto a una configuración con exactamente un dataset.

Las imágenes, los documentos y el audio se anonimizan por las vías 3 y 4, después de subirlos a la plataforma; una colección puede mezclarlos con tablas. En un activo no tabular, las claves de columns son los elementos sensibles que hay que tratar —face, person, etcétera— y no nombres de columna. Use /nucleus/anonymization_methods/resolve para saber qué métodos admite cada elemento. Las vías 1 y 2 aceptan solo datos tabulares.

La respuesta llega de inmediato:

json

\{ "runId": "6f1c...", "status": "processing" \}

El dato que llega en la petición se registra como activo y se agrupa en una colección, para que la plataforma trate el conjunto como relacionado, y después se perfila; por eso la ejecución informa 10 durante un rato antes de que empiece la anonimización propiamente dicha.

Seguir la ejecución

GET /nucleus/anonymize/runs/\{run_id\}?token=SU_TOKEN

Responde desde el primer momento, así que no hay ninguna ventana en la que el identificador entregado todavía no se conozca.

statusSignificado
10Los conjuntos de datos se están registrando y perfilando.
50Terminada. El resultado está listo para recogerse.
51Fallida.

Cuando llega a 50, la respuesta incluye además lo que se ha producido, una entrada por conjunto entregado con su propio assetId:

json

\{

  "runId": "6f1c...",

  "status": "50",

  "anonymizedAssets": [

    \{ "assetId": "9ab3...", "name": "empleados_anonymized" \}

  ]

\}

Recoger los datos anonimizados

GET /nucleus/download/anonymized/\{run_id\}?token=SU_TOKEN

La API no sirve el dato en streaming. Firma cada objeto del almacenamiento y devuelve una URL temporal que cualquiera puede pedir con GET hasta que caduque, que es la forma habitual de entregar volúmenes grandes sin convertir la API en un intermediario de datos.

json

\{

  "runId": "6f1c...",

  "expiresInMinutes": 60,

  "datasets": [

    \{ "assetId": "9ab3...", "name": "empleados_anonymized",

      "url": "https://storage.googleapis.com/...&X-Goog-Signature=..." \}

  ]

\}

ParámetroSignificado
asset_idFirma solo ese conjunto. Por defecto se firman todos los de la ejecución.
expires_minutesCuánto tiempo sigue siendo válido cada enlace. Una hora por defecto, un día como máximo.

El fichero entregado es un CSV con ; como separador, todos los campos entrecomillados y una marca de orden de bytes (BOM), para que las hojas de cálculo lo abran con la codificación correcta.

Trate el enlace como un secreto. Su firma da acceso de lectura a datos personales anonimizados hasta que caduque, así que no conviene pegarlo en un ticket ni en un chat.

Una ejecución que no ha terminado responde 409 e indica su estado, en lugar de un éxito vacío.

Añadir filas a una entrega ya hecha

POST /nucleus/anonymize/increment?token=SU_TOKEN

Cuando llegan filas nuevas después de una entrega, no hay que volver a anonimizar todo. Se apunta a la ejecución anterior y se envía solo lo nuevo:

bash

curl -X POST "https://\<su-nucleus-api\>/nucleus/anonymize/increment?token=SU_TOKEN" \

     -F "run_id=ID_DE_LA_EJECUCION_ANTERIOR" \

     -F "files=@empleados_filas_nuevas.csv" \

     -F "files=@ausencias_filas_nuevas.csv"

La configuración no se envía: se lee de la ejecución que se continúa. Un valor que ya había aparecido conserva la sustitución que recibió, un identificador nuevo no repite ninguno anterior, y las fechas de una persona ya vista se mueven el mismo intervalo.

Conviene conocer dos reglas antes de usarlo:

  • Lo que ya se entregó no se vuelve a procesar. El texto libre no es reproducible —la detección ejecuta un modelo y la regeneración redacta prosa nueva—, así que volver a pasarlo cambiaría lo que el destinatario ya tiene.

  • Cada tabla de la ejecución necesita su fichero, aunque solo lleve la cabecera. Un incremento parcial dejaría algunas tablas al día y otras no, con claves ajenas apuntando a filas que no existen.

La procedencia, el país y el caso de uso se heredan de los activos originales, así que un incremento no puede declarar algo distinto de la entrega a la que pertenece.

Revertir una anonimización

POST /nucleus/deanonymize

Restaura los valores originales de las columnas indicadas, usando la tabla de equivalencias guardada para ese activo. Solo se pueden revertir los métodos reversibles, y solo mientras se conserve esa tabla: un activo cuyas equivalencias se destruyeron no se puede recuperar.

json

\{

  "token": "SU_TOKEN",

  "assetId": "9ab3...",

  "columns": ["nombre", "apellidos"]

\}

Sintetizar

Crear datos sintéticos con la API tiene dos pasos: primero se entrena un sintetizador y después se generan datos con él.

1. EntrenarPOST /nucleus/synthesize?algorithm=ALGORITMO&token=SU_TOKEN

ALGORITMO es uno de generic, transactional o relational. Se indica el activo y las opciones de entrenamiento; los tipos de columna se toman automáticamente del análisis, así que no hay que enumerarlos.

json

\{

  "assetId": "a1b2c3d4-...",

  "synthesizerName": "clientes_v1",

  "synthesizerDescription": "Modo calidad",

  "epochs": 200,

  "batchSize": 256,

  "amplify": "quality",

  "constraints": ["age\>=18"]

\}

bash

curl -X POST "https://\<su-nucleus-api\>/nucleus/synthesize?algorithm=generic&token=SU_TOKEN" \

     -H "Content-Type: application/json" \

     -d @synthesize_config.json

La respuesta incluye un runId y el status del entrenamiento. El entrenamiento corre en segundo plano; su progreso se consulta con los endpoints de ejecuciones que se ven más abajo. (También se puede entrenar desde una base de datos conectada, indicando databaseId y tableName en lugar de assetId.)

2. Generar — una vez terminado el entrenamiento, se crea un conjunto sintético a partir del sintetizador entrenado:

POST /nucleus/generate/\{run_id\}?num_rows=100000&token=SU_TOKEN

Para muestras pequeñas y a demanda se puede usar POST /nucleus/generate/realtime/\{run_id\}?num_rows=...&replicate_outliers=yes|no, que devuelve las filas directamente (hasta 5.000).

3. Descargar — se recupera el conjunto generado en el formato que se prefiera:

GET /nucleus/download/syntheticdata/\{run_id\}?file_format=CSV&token=SU_TOKEN

Formatos disponibles: CSV, PARQUET, JSON.

Gestionar ejecuciones

EndpointPara qué sirve
GET /nucleus/runs/listLista todos sus sintetizadores entrenados.
GET /nucleus/runs/info/\{run_id\}Detalles y estado de un sintetizador.
GET /nucleus/runs/logs/\{run_id\}Registros de entrenamiento de una ejecución.
POST /nucleus/uploadmodelSube un sintetizador entrenado localmente con Nucleus Edge

Estos endpoints cubren las ejecuciones de sintetizadores. Una ejecución de anonimización se sigue con GET /nucleus/anonymize/runs/\{run_id\}.

Todos los endpoints de ejecuciones reciben el token como parámetro de consulta.

API | Dedomena AI Documentation | Dedomena AI