Third-AI-Uniandes — Flujos HTTP para APIM
Documentación de cómo el CLI de AI Uniandes consume las APIs para integración con APIM.
Base URL: Sustituya https://{apim-host}/{api-suffix} por la URL de su APIM.
Servicios del CLI
Servicio
Uso
Scope OAuth2
Nota
UploadDocument
Upload, estado, eliminación
UploadDocument
Principal de ingesta
DocumentClassifier
DocumentGroups + batch
DocumentClassifier
Visibilidad restringida
ClientAssistant
Chat con asistentes
ClientAssistant
Preguntas RAG
OnBase
Navegación de archivos
OnBase
Requiere bearer
1. Autenticación OAuth2 client_credentials

POST https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token
Scopes por servicio
Servicio
Scope
UploadDocument
api://FA-<env>-AIUniandes-UploadDocument/.default
DocumentClassifier
api://FA-<env>-AIUniandes-DocumentClassifier/.default
ClientAssistant
api://FA-<env>-AIUniandes-ClientAssistant/.default
OnBase
api://FA-<env>-AIUniandes-OnBase/.default
Ejemplo de obtención de token
HTTP Request
POST https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id={client_id}
&client_secret={client_secret}
&scope=api://FA-QA-AIUniandes-UploadDocument/.defaultRespuesta satisfactoria · 200 OK
{
"token_type": "Bearer",
"expires_in": "<segundos>",
"ext_expires_in": "<segundos>",
"access_token": "<token>"
}Headers comunes
HTTP Headers
Accept: application/json
Authorization: Bearer {access_token}
Content-Type: application/json2. Flujo de ingesta para asistentes RAG
Para agregar un archivo de contexto a un asistente existente, el consumidor ejecuta tres operaciones: subir el archivo, solicitar su procesamiento y consultar el estado. Conserve el file_id retornado por la carga y utilícelo como document_id al consultar el estado.
Alcance de este ejemplo: ingesta directa con UploadDocument. Requiere el ID del asistente de destino. Los valores de los ejemplos son ilustrativos; los campos y respuestas se contrastaron con el código de UploadDocument entregado. Las rutas y la autenticación externas de APIM siguen pendientes de contrastar con su configuración.

1. Subir el archivo
POST /api/v1/documents/upload/assistant
Formato: multipart/form-data. Envíe un archivo por petición. Permita que cURL genere el header Content-Type con su boundary.
Campo
Tipo
Valor
Requerido
file
binario
Contenido del archivo; el ejemplo usa un PDF con MIME application/pdf
Sí
source
texto
CONTEXT_ASSISTANT
Sí
conversation_id
texto
ID de conversación, si aplica
No
cURL · carga
curl --request POST "{base_url}/api/v1/documents/upload/assistant" \
--header "Authorization: Bearer {upload_token}" \
--header "Accept: application/json" \
--form "file=@./documento.pdf;type=application/pdf" \
--form "source=CONTEXT_ASSISTANT"Respuesta · 200 OK
{
"file_name": "documento.pdf",
"file_id": "2da40ce5-4c9f-4cce-a76d-7ff7304c4fd1",
"status": "success"
}success describe el resultado de la carga HTTP. El archivo queda registrado con estado UPLOADED; aún requiere solicitar su procesamiento. La asociación al asistente se realiza en el siguiente paso.
2. Solicitar el procesamiento
POST /api/v1/documents/process
Envíe JSON con los tres campos. id_application identifica el asistente al que se asociará el documento; type debe ser exactamente context_assistant. El documento debe estar en estado UPLOADED.
Campo
Tipo
Valor
Requerido
file_id
texto
ID del archivo retornado por la carga
Sí
id_application
texto
ID del asistente al que se asociará el documento
Sí
type
texto
context_assistant
Sí
cURL · procesamiento con JSON
curl --request POST "{base_url}/api/v1/documents/process" \
--header "Authorization: Bearer {upload_token}" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"file_id": "2da40ce5-4c9f-4cce-a76d-7ff7304c4fd1",
"id_application": "{assistant_id}",
"type": "context_assistant"
}'Respuesta · 200 OK
{
"file_id": "2da40ce5-4c9f-4cce-a76d-7ff7304c4fd1",
"application_id": "{assistant_id}",
"status": "processing_started"
}Operación asíncrona: este endpoint devuelve 200 OK al iniciar el procesamiento. Esa respuesta todavía no indica que el archivo esté listo para las consultas RAG.
3. Consultar el estado
GET /api/v1/document/{document_id}/status
Sustituya document_id por el file_id recibido. Repita la consulta hasta alcanzar READY o un estado terminal de error/eliminación. Si vence el tiempo de espera del cliente, conserve el ID y consulte de nuevo; el vencimiento no demuestra que el procesamiento haya fallado.
Campo
Tipo
Valor
Requerido
document_id
texto · ruta
El file_id retornado por la carga; se incluye en la URL
Sí
cURL · estado
curl --request GET "{base_url}/api/v1/document/2da40ce5-4c9f-4cce-a76d-7ff7304c4fd1/status" \
--header "Authorization: Bearer {upload_token}" \
--header "Accept: application/json"Ejemplo de respuesta · 200 OK
{
"id": "2da40ce5-4c9f-4cce-a76d-7ff7304c4fd1",
"filename": "documento.pdf",
"status": "READY",
"source": "CONTEXT_ASSISTANT",
"blob_name": "container/documento.pdf",
"application_id": "{assistant_id}",
"id_conversation": null,
"origin": "PORTAL_WEB",
"error": false,
"schedule_frequency": null
}Cómo interpretar el estado
Estado
Significado para el consumidor
Acción
UPLOADED
Archivo recibido; no confirma disponibilidad RAG
Solicitar procesamiento si aún no se ha solicitado
PROCESSED y demás estados intermedios
El documento todavía figura en procesamiento
Continuar consultando
READY
Documento listo según el servicio
Finalizar el seguimiento con éxito
ERROR o INTERRUPTED
Procesamiento fallido o interrumpido
Detener el seguimiento y revisar el incidente con el ID del archivo
DELETED
Documento eliminado
Detener el seguimiento; no es una carga exitosa
El CLI entregado consulta cada 5 segundos y espera hasta 300 segundos por defecto para este flujo. Son ajustes del cliente, no un tiempo garantizado de procesamiento. Su implementación detiene el seguimiento también en PROCESSED; para confirmar disponibilidad, esta guía utiliza READY, coherente con los estados del backend.
3. Flujo de chat con asistentes

POST /api/v1/ai-assistant/chat/{assistant_id}
Modelos disponibles
Alias
model
model_label
gpt-5
GPT_5_CHAT_UNIANDES
Open AI gpt-5-chat
gpt-4.1
GPT_4_1_CHAT_UNIANDES
Open AI gpt-4.1-chat
gpt-4o
GPT_4o_CHAT_UNIANDES
Open AI gpt-4o-chat
deepseek
DEEPSEEK_R1_CHAT_UNIANDES
DeepSeek R1 chat
Payload completo
JSON Request
{
"id": "{message_uuid}",
"userName": "script-rag-chat",
"roles": "ADMINISTRATIVE,STUDENT,TEACHER,ADMINISTRATOR-ASSISTANT,OWNER-ASSISTANT,USER-TD",
"state": "INITIALIZED",
"category": "",
"question": "Cual es la politica de homologaciones?",
"answer": " ",
"answerTyping": " ",
"answerRating": 0,
"reasonRating": "",
"refinedAnswer": "",
"academicCategory": null,
"keyWords": [],
"links": [],
"restrictionService": null,
"idConversation": "{conversation_uuid}",
"files": [],
"model": "GPT_5_CHAT_UNIANDES",
"model_label": "Open AI gpt-5-chat",
"is_open": "NO"
}Campos de respuesta
Campo
Tipo
Descripción
answer
string
Texto de respuesta
id
UUID
ID del mensaje
idConversation
UUID
Reutilizar para el hilo
keyWords
array
Palabras clave
links
array
Referencias citadas
4. Descarga de metadata desde OnBase

Listado por navegación
GET /api/v1/onbase/files?path={path}&page_size={n}
HTTP Request
GET /api/v1/onbase/files?path=Secretaria/Actas/&page_size=50
Authorization: Bearer {onbase_token}
Accept: application/jsonBúsqueda paginada
GET /api/v1/onbase/files?search={texto}&page_size={n}&cursor={cursor}
Mapeo OnBase → Excel
Campo Excel
Origen
Transformación
source
—
Fijo: ONBASE
document_onbase_id
file_id
Directo
name
name
Directo
typology
document_type
Directo
category
path
Directo
visibility
visibility
CLASSIFIED → RESTRICTED
action
—
Fijo: NEW
5. Ingesta RAG Institutional simple
Para agregar un archivo local a un RAG institucional existente, conserve su application_id y el file_id devuelto por la carga. El consumidor sube el archivo, configura permisos si es restringido, solicita clasificación y consulta el avance hasta que el documento esté disponible. En las peticiones de este flujo, envíe application_id únicamente al solicitar la clasificación.
Caso
Permisos del documento
Secuencia
PUBLIC
Sin restricción adicional por DocumentGroup en este flujo
Carga → clasificación → estado del trabajo → estado del documento
RESTRICTED
Grupos y/o usuarios definidos en un DocumentGroup
Carga → DocumentGroup → clasificación → estado del trabajo → estado del documento
En los ejemplos, {upload_base_url} es la base de UploadDocument expuesta en APIM y {classifier_base_url} la de DocumentClassifier. Sustituya cada una por el host y sufijo configurados para ese servicio. Los tokens también corresponden al servicio de cada llamada.
La visibilidad del documento y la autenticación del servicio son conceptos distintos: PUBLIC no significa que la API permita peticiones anónimas.

1. Subir el archivo local
POST /api/v1/document/upload/institutional
Use multipart/form-data y envíe un archivo por petición. cURL genera automáticamente el Content-Type y su boundary. Para varios documentos, repita la carga y reúna los identificadores devueltos.
Campo
Tipo
Valor
Requerido
file
binario
Contenido del archivo; el ejemplo utiliza un PDF con MIME application/pdf
Sí
visibility
texto
PUBLIC o RESTRICTED. Por defecto: PUBLIC
No
cURL · carga pública
curl --request POST "{upload_base_url}/api/v1/document/upload/institutional" \
--header "Authorization: Bearer {upload_token}" \
--header "Accept: application/json" \
--form "file=@./politica-institucional.pdf;type=application/pdf" \
--form "visibility=PUBLIC"Respuesta · 200 OK
{
"file_name": "politica-institucional.pdf",
"file_id": "7e121456-3ef6-48ce-847d-c01e91ce88af",
"status": "success"
}La respuesta confirma la carga. El documento queda en UPLOADED; success todavía no indica que pueda utilizarse en consultas RAG. El servicio asigna source=CONTEXT_INSTITUTIONAL cuando se omite la fuente, y registra origin=PORTAL_WEB para la carga local.
Para un documento restringido, cambie el formulario a visibility=RESTRICTED y complete el paso de permisos antes de clasificarlo. El campo visibility por sí solo no define quiénes pueden acceder.
2. Configurar permisos cuando el documento sea restringido
POST /api/v1/document-groups
Envíe JSON con los grupos y/o usuarios autorizados. En este caso de uso debe existir al menos un grupo o usuario permitido. Sustituya los nombres ilustrativos por identidades válidas de su organización. Para un documento público puede omitir este paso.
Campo
Tipo
Valor
Requerido
file_id
texto · UUID
ID del archivo retornado por la carga
Sí
allowed_groups
arreglo de objetos
Grupos autorizados: {"name_group": "Secretaria-General"}
Condicional: grupos y/o usuarios para restringir
allowed_users
arreglo de objetos
Usuarios autorizados: {"username": "[email protected]"}
Condicional: grupos y/o usuarios para restringir
cURL · crear DocumentGroup con JSON
curl --request POST "{classifier_base_url}/api/v1/document-groups" \
--header "Authorization: Bearer {classifier_token}" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"file_id": "7e121456-3ef6-48ce-847d-c01e91ce88af",
"allowed_groups": [
{
"name_group": "Secretaria-General"
}
],
"allowed_users": [
{
"username": "[email protected]"
}
]
}'Respuesta: 201 Created, con el DocumentGroup en data. El servicio configura la restricción del archivo a partir de las identidades indicadas. No envíe allowed_groups ni allowed_users como partes del formulario de carga.
Si el archivo ya tiene un DocumentGroup, volver a ejecutar el POST devuelve el existente y no modifica sus permisos. Utilice PUT /api/v1/document-groups/{file_id} para actualizarlos; el ejemplo se conserva al final de esta sección.
3. Solicitar clasificación
POST /api/v1/document-groups/classify/batch
La misma operación se utiliza para uno o varios archivos del RAG institucional. Incluya los archivos ya cargados y, para los restringidos, con sus permisos configurados.
Campo
Tipo
Valor
Requerido
file_ids
arreglo de textos
Identificadores retornados por la carga; un elemento para un solo archivo
Sí
application_id
texto
ID del RAG institucional de destino
Sí
cURL · clasificación con JSON
curl --request POST "{classifier_base_url}/api/v1/document-groups/classify/batch" \
--header "Authorization: Bearer {classifier_token}" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"file_ids": [
"7e121456-3ef6-48ce-847d-c01e91ce88af"
],
"application_id": "{application_id}"
}'Respuesta · 202 Accepted
{
"data": {
"job_id": "7bfa2132-9a41-45dd-a0bd-a6e3cd4fb8e2",
"status_url": "/api/v1/document-groups/classify/status/7bfa2132-9a41-45dd-a0bd-a6e3cd4fb8e2"
}
}202 Accepted confirma que se inició el trabajo asíncrono. Conserve data.job_id. La ruta data.status_url es relativa al servicio DocumentClassifier; úsela con la base correspondiente de APIM.
El clasificador solicita el procesamiento institucional de los archivos nuevos que pasan sus validaciones. En esta secuencia, la continuación del consumidor es consultar el estado del trabajo.
4. Consultar el trabajo y revisar sus errores
GET /api/v1/document-groups/classify/status/{job_id}
Campo
Tipo
Valor
Requerido
job_id
texto · ruta
Identificador data.job_id recibido al solicitar clasificación
Sí
cURL · estado de clasificación
curl --request GET "{classifier_base_url}/api/v1/document-groups/classify/status/7bfa2132-9a41-45dd-a0bd-a6e3cd4fb8e2" \
--header "Authorization: Bearer {classifier_token}" \
--header "Accept: application/json"Ejemplo de respuesta · 200 OK · un archivo sin errores
{
"job_id": "7bfa2132-9a41-45dd-a0bd-a6e3cd4fb8e2",
"status": "Completed",
"created_at": "2026-09-17T14:00:00+00:00",
"last_updated_at": "2026-09-17T14:00:10+00:00",
"custom_status": {
"job_id": "7bfa2132-9a41-45dd-a0bd-a6e3cd4fb8e2",
"total_files": 1,
"total_batches": 1,
"batches_completed": 1,
"validated_ok": 1,
"validated_fail": 0,
"classified_ok": 1,
"classified_fail": 0,
"classified_already_indexed": 0,
"errors": [],
"current_phase": "COMPLETED"
},
"output": null
}Esta respuesta contiene status y custom_status directamente en la raíz del JSON. Revise custom_status para conocer el resultado por archivo; output puede ser null.
Dato
Qué indica
Acción
status=Running
Trabajo en curso
Continuar consultando
status=Completed
Terminó la orquestación de clasificación; puede incluir fallos por archivo
Revisar contadores y errors; seguir el estado de los archivos sin errores
status=Failed
Falló la orquestación
Detener el seguimiento del trabajo y revisar el incidente
custom_status.validated_fail, classified_fail y errors
Fallos de validación o clasificación; los errores identifican el file_id, la fase y el detalle
Resolver los fallos de esos archivos antes de considerarlos exitosos
Clasificación y disponibilidad: Completed no garantiza que el documento esté listo para consultas. Para los archivos sin errores, complete el siguiente paso hasta READY.
5. Confirmar disponibilidad del documento
GET /api/v1/document/{document_id}/status
Esta consulta corresponde a UploadDocument. Use el file_id recibido en la carga; el job_id identifica el trabajo de clasificación y no se utiliza en esta ruta.
Campo
Tipo
Valor
Requerido
document_id
texto · ruta
El file_id del documento que se desea consultar
Sí
cURL · estado del documento
curl --request GET "{upload_base_url}/api/v1/document/7e121456-3ef6-48ce-847d-c01e91ce88af/status" \
--header "Authorization: Bearer {upload_token}" \
--header "Accept: application/json"Ejemplo de respuesta · 200 OK
{
"id": "7e121456-3ef6-48ce-847d-c01e91ce88af",
"filename": "politica-institucional.pdf",
"status": "READY",
"source": "CONTEXT_INSTITUTIONAL",
"blob_name": "container/politica-institucional.pdf",
"application_id": "{application_id}",
"id_conversation": null,
"origin": "PORTAL_WEB",
"error": false,
"schedule_frequency": null
}Estado del documento
Significado
Acción
READY
Documento listo según el servicio
Finalizar con éxito para ese archivo
UPLOADED, PROCESSING, PROCESSED y otros estados intermedios
Disponibilidad todavía no confirmada
Seguir consultando; si permanece en UPLOADED, revisar el resultado del trabajo de clasificación
ERROR o INTERRUPTED
Procesamiento fallido o interrumpido
Detener el seguimiento y revisar el incidente con el ID del archivo
DELETED
Documento eliminado
Detener el seguimiento; no es una carga exitosa
Defina un intervalo y un tiempo máximo de espera en el cliente. Si este tiempo vence, conserve job_id y file_id para retomar las consultas; el vencimiento local no demuestra que el servicio haya cancelado el procesamiento.
Actualizar DocumentGroup
PUT /api/v1/document-groups/{file_id}
JSON Request
{
"allowed_groups": [{ "name_group": "Secretaria-General" }],
"allowed_users": [{ "username": "[email protected]" }]
}Upload desde OnBase
POST /api/v1/documents/upload/onbase
JSON Request
{
"file_id": "{document_onbase_id}",
"source": "CONTEXT_INSTITUTIONAL"
}6. Eliminación de archivo institucional

7. Recomendaciones APIM
Producto APIM
Endpoints
Ingesta asistentes
upload assistant, process, status, delete
Chat asistentes
/ai-assistant/chat/{id}
Ingesta institucional
upload institutional, upload onbase, document-groups, classify
Consulta OnBase
/onbase/files
8. Diferencias importantes
1. type en POST /documents/process = context_assistant (guión bajo)
2. Ingesta institucional usa DocumentClassifier batch, NO /document/process/institutional
3. OnBase requiere bearer token (no es anónimo)