MIRA · Referencia de API para desarrolladores

API de validación documental

El servicio MIRA expone endpoints ejecutables para validar PDF, imágenes y evidencia multimedia mediante QR, códigos de barras, detección de rostros, detección de firmas, comparación de imágenes, prompts y OCR de texto. Cada endpoint ejecuta una sola regla y devuelve su propio resultado. La orquestación de varias reglas en una decisión completa se realiza con los endpoints de workflow.

URL base https://api.miratrust.io
PDFQR · Barcode · Rostro · Firma · Imagen · Prompt · Texto · Evidencia
JPEG · PNG · TIFFPrompt · Texto · Evidencia
MP4 · WebM · MPEG · QuickTimeEvidencia (multipart)

AUTHAutenticación

Para consumir un endpoint protegido de MIRA primero se obtiene un access token y luego se envía en la cabecera de la solicitud:

HEADER
Authorization: Bearer {ACCESS_TOKEN}

El backend no ejecuta los flujos OAuth: recibe y valida el access token emitido por Cognito. El JWT debe contener token_use=access; un ID token no es válido. GET /health y la interfaz Swagger son públicos y no requieren Bearer token.

Flujo 1 · Usuarios — Authorization Code con PKCE

Se usa cuando hay una persona frente a una aplicación web o móvil. PKCE protege el intercambio del código y permite que una aplicación pública no guarde un client_secret. Primero se dirige el navegador a una URL como esta:

GET /oauth2/authorize
https://mitra-trust.auth.us-east-1.amazoncognito.com/oauth2/authorize
  ?response_type=code
  &client_id={PUBLIC_CLIENT_ID}
  &redirect_uri={URL_CALLBACK_ENCODED}
  &scope=openid+email
  &code_challenge={CODE_CHALLENGE}
  &code_challenge_method=S256
  &state={RANDOM_STATE}

Después del login, Cognito redirige al callback registrado con un code. La aplicación debe comprobar que el state recibido coincida con el que guardó y luego intercambia el código por tokens:

POST /oauth2/token
curl --request POST "https://mitra-trust.auth.us-east-1.amazoncognito.com/oauth2/token" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "client_id={PUBLIC_CLIENT_ID}" \
  --data-urlencode "code={AUTHORIZATION_CODE}" \
  --data-urlencode "redirect_uri={URL_CALLBACK}" \
  --data-urlencode "code_verifier={CODE_VERIFIER}"
200 · JSON
{
  "access_token": "eyJraWQiOi...",
  "id_token": "eyJraWQiOi...",
  "refresh_token": "...",
  "expires_in": 3600,
  "token_type": "Bearer"
}

Solo se usa access_token para llamar a MIRA. Los usuarios autorizados deben pertenecer al grupo de Cognito MIRA_ADMIN o MIRA_STANDARD, y el claim client_id del token debe corresponder al App Client de frontend configurado con COGNITO_CLIENT_ID. Si la federación está configurada (Microsoft Entra ID, Okta, SAML/OIDC), MIRA siempre recibe un token emitido por Cognito, nunca el token del IdP externo.

Flujo 2 · Sistemas — Client Credentials

Se usa para integraciones backend-to-backend, procesos batch o servicios automáticos. No representa a un usuario ni abre un navegador. El sistema necesita un client_id, un client_secret (en un gestor de secretos) y el scope mira-api/execute.

POST /oauth2/token
curl --request POST "https://mitra-trust.auth.us-east-1.amazoncognito.com/oauth2/token" \
  --user "{CLIENT_ID}:{CLIENT_SECRET}" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "scope=mira-api/execute"

El client_secret se usa únicamente al solicitar el token a Cognito y nunca debe enviarse a una API de MIRA.

BASEConvenciones

  • Las rutas JSON reciben Content-Type: application/json.
  • Todos los endpoints documentales aceptan Base64 puro.
  • QR, BARCODE, FACE, SIGNATURE e IMAGE solo eliminan el prefijo exacto data:application/pdf;base64,.
  • PROMPT y TEXT aceptan un Data URL genérico y eliminan todo lo anterior a la primera coma.
  • Los documentos y videos no deben superar los 20 MB.
  • Las páginas se numeran desde 1.

HTTPHeaders comunes

CampoObligatorioDescripción
Authorization: Bearer {ACCESS_TOKEN}Access token de Cognito válido.
Content-Type: application/jsonEn endpoints JSON. Permite deserializar el cuerpo JSON.
Content-Type: multipart/form-dataEn EVIDENCE. curl agrega el boundary automáticamente con --form; no debe escribirse manualmente.
Idempotency-Key: {UUID}En creación/ejecución de workflows. Evita duplicados ante reintentos.

Resumen de endpoints

MétodoRutaPluginEntrada
POST/rule/document/qr/readqrPDF en Base64
POST/rule/document/barcode/readbarcodePDF en Base64
POST/rule/document/face/readfacePDF en Base64
POST/rule/document/signature/readsignaturePDF en Base64
POST/rule/document/image/validateimagePDF y referencias en Base64
POST/rule/document/prompt/evaluatepromptPDF o imagen en Base64
POST/rule/document/text/readtextPDF o imagen en Base64
POST/api/rule/evidence/prompt/evaluateevidenceArchivo multipart
POST/api/admin/workflows/{workflowId}/versionsworkflowDefinición JSON
POST/api/workflows/{workflowId}/executeworkflowDocumento JSON
GET/api/workflow-executions/{executionId}workflowParámetro de ruta

REGLASEndpoints de reglas

Todos los endpoints de reglas reciben un cuerpo JSON con Content-Type: application/json y un Bearer token válido. Los campos marcados como “No” pueden omitirse; omitir no equivale a enviar null.

01Lectura de códigos QR

Busca códigos QR dentro de un PDF y los compara con los valores esperados.

POST/rule/document/qr/read

Solicitud

SOLICITUD
{
  "pdfBase64": "JVBERi0xLjQK...",
  "rule": {
    "id": "RULE-QR-01",
    "type": "QR",
    "weight": 20,
    "minMatch": 100,
    "expectedCount": 1,
    "expectedValues": ["https://example.com/document/123"],
    "pages": [1, 2]
  }
}

Campos

CampoTipoObligatorioDescripción
pdfBase64stringPDF en Base64 puro o con el prefijo exacto data:application/pdf;base64,. No puede estar vacío.
ruleobjectNoConfiguración de la regla QR. Si se omite, cualquier QR detectado puede aprobar.
rule.idstringNoIdentificador informativo.
rule.typestringNoTipo informativo.
rule.weightdecimalNoPeso de la regla.
rule.minMatchintegerNoUmbral informativo.
rule.expectedCountintegerNoCantidad esperada informativa.
rule.expectedValuesstring[]NoValores QR aceptados.
rule.pagesinteger[]NoPáginas a analizar, numeradas desde 1. Si se omite o queda vacío, se analizan todas.

Comportamiento

Si expectedValues está vacío, cualquier QR detectado obtiene score=100. Con valores esperados, la comparación es exacta tras recortar espacios laterales y pasar a minúsculas.

score solo puede ser 0 o 100. detectedCount cuenta combinaciones únicas de valor normalizado y página. passed es true únicamente con un QR de score=100.

Respuesta de ejemplo

200 · JSON
{
  "hasQr": true,
  "passed": true,
  "score": 100,
  "foundValue": "https://example.com/document/123",
  "detectedCount": 1,
  "foundValues": [
    { "value": "https://example.com/document/123", "page": 1, "score": 100 }
  ]
}

02Lectura de códigos de barras

Busca códigos CODE 128, CODE 39, EAN-13, EAN-8, UPC-A, UPC-E, PDF417, ITF y Codabar en un PDF.

POST/rule/document/barcode/read

Solicitud

SOLICITUD
{
  "pdfBase64": "JVBERi0xLjQK...",
  "rule": {
    "id": "RULE-BARCODE-01",
    "type": "BARCODE",
    "weight": 15,
    "minMatch": 100,
    "expectedCount": 1,
    "expectedValues": ["7801234567894"],
    "regions": [ { "pages": [1] } ]
  }
}

Campos

CampoTipoObligatorioDescripción
pdfBase64stringPDF en Base64 puro o con el prefijo exacto data:application/pdf;base64,. No puede estar vacío.
ruleobjectNoConfiguración BARCODE. Si se omite, se aplican los predeterminados.
rule.idstringNoIdentificador. Predeterminado: null.
rule.typestringNoTipo devuelto. Predeterminado: BARCODE.
rule.weightnumberNoPeso. Predeterminado: 0.
rule.minMatchintegerNoMatch mínimo para aprobar.
rule.expectedCountintegerNoMetadata de cantidad esperada.
rule.expectedValuesstring[]NoCódigos aceptados. Predeterminado: lista vacía (permite cualquiera).
rule.regionsobject[]NoRegiones usadas únicamente para seleccionar páginas.
rule.regions[].pagesinteger[]NoPáginas a analizar. Sin regiones se analizan todas.

Comportamiento

La comparación aplica Trim() y elimina el espacio ASCII, pero no tabulaciones ni todos los espacios Unicode; distingue mayúsculas y minúsculas. Devuelve como máximo un código por página. expectedCount es metadata y no interviene en passed.

foundMatch solo puede ser 0 o 100. Como minMatch no se restringe, un valor ≤ 0 puede aprobar sin detecciones y uno > 100 nunca aprueba. scoreContribution es el weight completo si aprueba; si no, 0.

Respuesta de ejemplo

200 · JSON
{
  "id": "RULE-BARCODE-01",
  "type": "BARCODE",
  "weight": 15,
  "minMatch": 100,
  "expectedCount": 1,
  "foundValue": "7801234567894",
  "foundMatch": 100,
  "passed": true,
  "scoreContribution": 15,
  "details": {
    "detectedCount": 1,
    "foundValues": [ { "value": "7801234567894", "format": "EAN_13", "page": 1 } ]
  }
}

03Detección de rostros

Detecta rostros mediante Google Cloud Vision.

POST/rule/document/face/read

Solicitud

SOLICITUD
{
  "pdfBase64": "JVBERi0xLjQK...",
  "rule": {
    "id": "RULE-FACE-01",
    "type": "FACE",
    "weight": 20,
    "minMatch": 100,
    "expectedCount": 1,
    "regions": [ { "pages": [1] } ]
  }
}

Campos

CampoTipoObligatorioDescripción
pdfBase64stringPDF en Base64 puro o con el prefijo exacto data:application/pdf;base64,. No puede estar vacío.
ruleobjectNoConfiguración FACE. Si se omite, se usa la predeterminada.
rule.idstringNoIdentificador de la regla. Predeterminado: null.
rule.typestringNoTipo devuelto. Predeterminado: FACE.
rule.weightintegerNoPeso. Predeterminado: 0.
rule.minMatchintegerNoPorcentaje mínimo para aprobar. Predeterminado: 0.
rule.expectedCountintegerNoRostros esperados. Predeterminado: 1; si se envía, debe ser > 0.
rule.regions[].pagesinteger[]NoPáginas a analizar, desde 1. Sin regiones se analiza solo la página 1.

Comportamiento

Sin regiones solo se analiza la primera página; las regiones seleccionan páginas, no recortan por coordenadas. Páginas ≤ 0 se descartan; una página mayor al total puede terminar en 500.

foundMatch = min(100, detectedCount × 100 / expectedCount). Si aprueba, scoreContribution es el weight completo; si no, el aporte proporcional weight × foundMatch / 100, redondeado a dos decimales.

Respuesta de ejemplo

200 · JSON
{
  "id": "RULE-FACE-01",
  "type": "FACE",
  "weight": 20,
  "minMatch": 100,
  "foundMatch": 100,
  "passed": true,
  "scoreContribution": 20,
  "expectedCount": 1,
  "details": {
    "detectedCount": 1,
    "foundValues": [
      { "value": "face_detected", "page": 1, "x": 0.32, "y": 0.11, "width": 0.18, "height": 0.24, "confidence": 0.98 }
    ]
  }
}

04Detección de firmas

Busca firmas cerca de palabras como firma, mandante, mandatario y notario, combinando Document AI con detección de tinta.

POST/rule/document/signature/read

Solicitud

SOLICITUD
{
  "pdfBase64": "JVBERi0xLjQK...",
  "rule": {
    "id": "RULE-SIGNATURE-01",
    "type": "SIGNATURE",
    "weight": 25,
    "minMatch": 80,
    "expectedCount": 1,
    "regions": [
      { "pages": [1], "x": 0.1, "y": 0.7, "width": 0.8, "height": 0.2 }
    ]
  }
}

Campos

CampoTipoObligatorioDescripción
pdfBase64stringPDF en Base64 puro o con el prefijo exacto data:application/pdf;base64,. No puede estar vacío.
ruleobjectNoConfiguración SIGNATURE. Si se omite, se usa la predeterminada.
rule.idstringNoIdentificador de la regla. Predeterminado: null.
rule.typestringNoTipo devuelto. Predeterminado: SIGNATURE.
rule.weightintegerNoPeso. Predeterminado: 0.
rule.minMatchintegerNoUmbral entre 0 y 100. Predeterminado: 0.
rule.expectedCountintegerNoFirmas esperadas. Predeterminado: 1; debe ser > 0.
rule.regions[]object[]NoMetadata devuelta en la respuesta (páginas, x, y, width, height informativos).

Comportamiento

Las regiones se devuelven como metadata; la implementación determina dinámicamente la zona de búsqueda a partir de las palabras clave (configurables a petición del cliente). La confidence es una métrica heurística de tinta entre 0 y 100.

minMatch cumple dos funciones: cada zona candidata debe alcanzar esa confianza de tinta para contarse, y luego foundMatch también debe alcanzar el umbral para aprobar.

Respuesta de ejemplo

200 · JSON
{
  "id": "RULE-SIGNATURE-01",
  "type": "SIGNATURE",
  "weight": 25,
  "minMatch": 80,
  "foundMatch": 100,
  "passed": true,
  "scoreContribution": 25,
  "expectedCount": 1,
  "regions": [
    { "pages": [1], "x": 0.1, "y": 0.7, "width": 0.8, "height": 0.2, "hasCoordinates": true }
  ],
  "details": {
    "detectedCount": 1,
    "foundValues": [
      { "value": "signature_detected_near_keyword", "keyword": "firma", "page": 1,
        "x": 0.2, "y": 0.7, "width": 0.45, "height": 0.12,
        "confidence": 92, "inkPixels": 430, "contourCount": 4 }
    ]
  }
}

05Validación de imágenes

Busca en el PDF una o más imágenes de referencia.

POST/rule/document/image/validate

Solicitud

SOLICITUD
{
  "pdfBase64": "JVBERi0xLjQK...",
  "rule": {
    "id": "RULE-IMAGE-01",
    "type": "IMAGE",
    "weight": 20,
    "minMatch": 80,
    "expectedValues": ["iVBORw0KGgoAAAANSUhEUg..."],
    "regions": [
      { "pages": "1,2", "x": 0, "y": 0, "width": 1, "height": 0.5 }
    ]
  }
}

Campos

CampoTipoObligatorioDescripción
pdfBase64stringPDF en Base64 puro o con el prefijo exacto. No puede estar vacío.
ruleobjectConfiguración de la regla IMAGE.
rule.typestringNoPredeterminado: IMAGE. Si se envía, debe ser exactamente IMAGE.
rule.minMatchintegerNoSimilitud mínima para aprobar. Predeterminado: 80. No se restringe al rango 0..100.
rule.expectedValuesstring[]Una o más referencias no vacías (Base64 puro o Data URL) que deben decodificar como imagen.
rule.regions[].pagesstringNoPáginas separadas por coma, p.ej. "1,2". Vacío significa todas.

Comportamiento

Las coordenadas de regions no se usan para recortar. La búsqueda se realiza en el cuadrante superior izquierdo que cubre el 45% del ancho y el 45% del alto de cada página seleccionada.

Se conserva una sola coincidencia. Cuando una página alcanza minMatch, las siguientes no se procesan, por lo que no se garantiza el máximo global. scoreContribution = weight × foundMatch / 100 si aprueba; si no, 0.

Respuesta de ejemplo

200 · JSON
{
  "id": "RULE-IMAGE-01",
  "type": "IMAGE",
  "weight": 20,
  "minMatch": 80,
  "foundMatch": 92.5,
  "passed": true,
  "scoreContribution": 18.5,
  "expectedValues": ["iVBORw0KGgoA..."],
  "details": {
    "detectedCount": 1,
    "foundValues": [
      { "value": null, "page": 1, "x": 0.2, "y": 0.1, "width": 0.3, "height": 0.15, "similarity": 92.5 }
    ]
  }
}

06Evaluación mediante prompt

Evalúa un PDF o una imagen.

POST/rule/document/prompt/evaluate

Solicitud

SOLICITUD
{
  "pdfBase64": "JVBERi0xLjQK...",
  "mimeType": "application/pdf",
  "rule": {
    "id": "RULE-PROMPT-01",
    "type": "PROMPT",
    "weight": 30,
    "minMatch": 80,
    "expectedValues": ["vigente", "firmado"],
    "prompt": "Verifica si el documento está vigente y firmado."
  }
}

Campos

CampoTipoObligatorioDescripción
pdfBase64stringPDF o imagen en Base64 puro o como Data URL. No puede estar vacío.
mimeTypestringNoPredeterminado: application/pdf. Para imágenes: image/jpeg o image/png.
ruleobjectConfiguración de la regla PROMPT.
rule.minMatchintegerNoUmbral entre 0 y 100. Predeterminado: 80.
rule.expectedValuesstring[]NoValores que orientan la evaluación. Predeterminado: lista vacía.
rule.promptstringInstrucción de negocio, con entre 10 y 4000 caracteres útiles.

Comportamiento

La regla debe tener type=PROMPT; prompt entre 10 y 4000 caracteres; minMatch entre 0 y 100; weight no negativo. expectedValues puede estar vacío.

foundMatch es un entero en 0..100. details.detectedCount es exactamente la cantidad de objetos en details.values.

Respuesta de ejemplo

200 · JSON
{
  "id": "RULE-PROMPT-01",
  "type": "PROMPT",
  "weight": 30,
  "minMatch": 80,
  "foundMatch": 90,
  "passed": true,
  "scoreContribution": 27,
  "details": {
    "detectedCount": 1,
    "result": "El documento está vigente y contiene una firma.",
    "values": [
      { "name": "vigencia", "value": "vigente",
        "evidence": "Fecha de vencimiento posterior a la fecha actual",
        "page": 1, "timestamp": null, "confidence": 0.95 }
    ]
  }
}

07Lectura y validación de texto

Extrae texto con OCR y busca los valores esperados.

POST/rule/document/text/read

Solicitud

SOLICITUD
{
  "documentBase64": "JVBERi0xLjQK...",
  "mimeType": "application/pdf",
  "rule": {
    "id": "RULE-TEXT-01",
    "type": "TEXT",
    "weight": 20,
    "minMatch": 80,
    "expectedValues": ["RUT 12.345.678-9"],
    "regions": [
      { "pages": "1", "x": 0, "y": 0, "width": 1, "height": 0.5 }
    ]
  }
}

Campos

CampoTipoObligatorioDescripción
documentBase64stringPDF o imagen en Base64 puro o como Data URL. No puede estar vacío.
mimeTypestringNoPredeterminado: application/pdf. Admite PDF, TIFF, JPEG y PNG. Para imagen o TIFF debe enviarse explícitamente.
rule.expectedValuesstring[]Uno o más textos esperados; no admite elementos vacíos.
rule.regions[].pagesstringNoPáginas separadas por coma. Vacío o sin enteros positivos significa todas.
rule.regions[].x/y/width/heightdecimalNoPosición esperada entre 0 y 1; el rango no se valida. Para aplicar coordenadas deben enviarse las cuatro.

Comportamiento

La comparación pasa a minúsculas, elimina acentos, reemplaza signos por espacios y colapsa espacios. Coincidencia exacta = 100; si un texto contiene al otro = 95; en otros casos usa distancia de Levenshtein.

Se devuelve solo la mejor coincidencia. foundMatch combina la similitud textual con la confianza OCR normalizada a 0..100. detectedCount indica si se construyó un candidato (0 o 1), no si aprobó.

Respuesta de ejemplo

200 · JSON
{
  "id": "RULE-TEXT-01",
  "type": "TEXT",
  "weight": 20,
  "minMatch": 80,
  "foundMatch": 98,
  "passed": true,
  "scoreContribution": 19.6,
  "details": {
    "detectedCount": 1,
    "expectedValue": "RUT 12.345.678-9",
    "matchedText": "RUT 12.345.678-9",
    "similarity": 100,
    "ocrConfidence": 98,
    "page": 1,
    "result": "Se encontró texto similar con 98% de confianza combinada.",
    "foundValues": [
      {
        "expectedValue": "RUT 12.345.678-9",
        "matchedText": "RUT 12.345.678-9",
        "page": 1,
        "similarity": 100,
        "ocrConfidence": 98,
        "combinedConfidence": 98,
        "boundingBox": { "x": 0.1, "y": 0.2, "width": 0.3, "height": 0.04 }
      }
    ]
  }
}

08Evaluación de evidencia multimedia

Recibe un archivo directamente (multipart). PDF e imágenes se procesan en memoria; los videos se suben a Google Cloud Storage y se evalúan desde allí.

POST/api/rule/evidence/prompt/evaluate

Solicitud

SOLICITUD · curl
curl --request POST "$BASE_URL/api/rule/evidence/prompt/evaluate" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form "file=@evidencia.mp4;type=video/mp4" \
  --form 'rule={"id":"RULE-EVIDENCE-01","type":"PROMPT","weight":30,"minMatch":80,"expectedValues":["casco"],"prompt":"Verifica si todas las personas utilizan casco."}' \
  --form "fps=1" --form "startOffset=0s" --form "endOffset=60s"

Campos

CampoTipoObligatorioDescripción
fileArchivoPDF, imagen o video no vacío.
rulestring JSONRegla PROMPT serializada como JSON válido.
mimeTypestringNoSobrescribe el Content-Type del archivo. Si se omite, se usa file.ContentType.
fpsnumberNoSolo video. Debe ser > 0 y ≤ 24.
startOffset / endOffsetstringNoSolo video. La validación local únicamente exige que terminen en s, p.ej. 0s, 60s.

Comportamiento

Formatos admitidos: PDF, JPEG, PNG, MP4, QuickTime, WebM y MPEG. El formato se decide por mimeType o el Content-Type declarado; el handler no inspecciona la firma binaria ni la extensión.

La respuesta tiene la misma estructura que una evaluación PROMPT. En video, los elementos pueden incluir timestamp en lugar de page. El objeto de video no se elimina automáticamente tras procesarse.

Respuesta de ejemplo

200 · JSON
{
  "id": "RULE-EVIDENCE-01",
  "type": "PROMPT",
  "weight": 30,
  "minMatch": 80,
  "foundMatch": 95,
  "passed": true,
  "scoreContribution": 28.5,
  "details": {
    "detectedCount": 1,
    "result": "El video muestra que todas las personas utilizan casco.",
    "values": [
      { "name": "uso de casco", "value": "cumple",
        "evidence": "Las personas visibles utilizan casco de seguridad.",
        "page": null, "timestamp": "00:00:12", "confidence": 0.96 }
    ]
  }
}

ORQUESTACIÓNWorkflows

Los endpoints de workflow combinan varias reglas en una sola decisión, con ejecución secuencial, puntaje ponderado y creación y ejecución idempotentes.

09Crear una versión del workflow

Crea y publica una nueva versión del workflow. La versión guarda el orden de los plugins, sus parámetros y la regla que calcula el resultado general. Disponible solo para el grupo MIRA_ADMIN.

POST /api/admin/workflows/{workflowId}/versions
POST /api/admin/workflows/{workflowId}/versions
Authorization: Bearer {ACCESS_TOKEN}
Idempotency-Key: {UUID}
Content-Type: application/json

Solicitud

SOLICITUD
{
  "name": "Validación de contrato",
  "basedOnVersion": 2,
  "changeNote": "Se agrega validación de firma",
  "activate": true,
  "definition": {
    "schemaVersion": 1,
    "execution": {
      "mode": "SEQUENTIAL",
      "onTechnicalError": "FAIL",
      "timeoutSeconds": 180
    },
    "steps": [
      {
        "id": "validar-qr",
        "pluginId": "qr",
        "pluginContractVersion": 1,
        "required": true,
        "weight": 40,
        "parameters": { "expectedValues": ["CONTRATO-123"], "pages": [1] }
      },
      {
        "id": "validar-firma",
        "pluginId": "signature",
        "pluginContractVersion": 1,
        "required": true,
        "weight": 60,
        "parameters": { "minMatch": 80, "expectedCount": 1 }
      }
    ],
    "decision": {
      "type": "WEIGHTED_THRESHOLD",
      "minScore": 80,
      "requireAllRequired": true
    }
  }
}

Campos

CampoTipoObligatorioDescripción
workflowIdstringIdentificador del workflow enviado en la ruta.
Idempotency-Keystring (UUID)Identificador único de la solicitud, enviado como header.
namestringNombre del workflow.
basedOnVersionintegerNoÚltima versión conocida. Se omite al crear la primera versión.
activatebooleanIndica si la nueva versión queda como versión activa.
definitionobjectDefinición completa del workflow (schemaVersion, execution, steps, decision).
definition.execution.modestringOrden de ejecución. En el ejemplo, SEQUENTIAL.
definition.steps[].weightnumberPuntaje máximo que puede aportar el paso.
definition.decision.typestringTipo de decisión: ALL_REQUIRED, ANY o WEIGHTED_THRESHOLD.

Comportamiento

Una versión publicada no se modifica: cualquier cambio crea una nueva. Con activate: true, esa versión queda como activeVersion. Si otro administrador ya creó una versión más nueva, el servicio debería responder 409 Conflict.

Idempotency-Key evita crear dos versiones ante reintentos. La misma clave y contenido devuelven el resultado original; reutilizarla con contenido distinto debe producir 409 Conflict. En WEIGHTED_THRESHOLD, los pesos deben sumar 100.

Respuesta de ejemplo

HTTPHTTP/1.1 201 Created
200 · JSON
{
  "workflowId": "validacion-contrato",
  "version": 3,
  "status": "PUBLISHED",
  "active": true,
  "definitionHash": "sha256:5d322e...",
  "createdAt": "2026-07-28T18:20:00Z"
}

10Ejecutar el workflow

Procesa el documento con la versión seleccionada del workflow. Puede ejecutarse de forma síncrona (/execute, resultado inmediato) o asincrónica (/executions, se consulta después).

POST /api/workflows/{workflowId}/execute
POST /api/workflows/{workflowId}/execute        # sincrono
POST /api/workflows/{workflowId}/executions     # asincrono (202 Accepted)
Authorization: Bearer {ACCESS_TOKEN}
Idempotency-Key: {UUID}
Content-Type: application/json

Solicitud

SOLICITUD
{
  "version": 3,
  "inputs": {
    "mainDocument": {
      "fileName": "contrato.pdf",
      "mimeType": "application/pdf",
      "contentBase64": "JVBERi0xLjQK..."
    }
  },
  "metadata": { "caseId": "CASE-93452" }
}

Campos

CampoTipoObligatorioDescripción
workflowIdstringIdentificador del workflow enviado en la ruta.
Idempotency-Keystring (UUID)Identificador único de la ejecución, como header. Evita duplicar ejecuciones ante reintentos.
versionintegerNoVersión publicada a ejecutar. Si se omite, se usa activeVersion.
inputs.mainDocument.mimeTypestringTipo MIME del documento, p.ej. application/pdf.
inputs.mainDocument.contentBase64stringContenido del documento codificado en Base64.
metadata.caseIdstringNoIdentificador del caso asociado. Es informativo y no modifica la decisión.

Comportamiento

La ejecución síncrona espera a que terminen todos los pasos y devuelve el resultado final (recomendada para workflows cortos). Si se supera timeoutSeconds, debería responder 504 Gateway Timeout con código WORKFLOW_TIMEOUT.

La ejecución asincrónica responde 202 Accepted con un statusUrl. La ejecución guarda siempre la versión resuelta y su definitionHash completo (SHA-256). Un passed=false es una validación rechazada, no un error técnico: la respuesta sigue siendo 200 OK.

Respuesta de ejemplo

HTTPHTTP/1.1 200 OK · (async) HTTP/1.1 202 Accepted
200 · JSON
{
  "executionId": "exe_01K1T9B8MZWR",
  "workflowId": "validacion-contrato",
  "workflowVersion": 3,
  "definitionHash": "sha256:5d322e...",
  "status": "COMPLETED",
  "decision": { "passed": false, "score": 40, "minScore": 80 },
  "steps": [
    { "id": "validar-qr", "pluginId": "qr", "status": "COMPLETED", "passed": true, "match": 100, "scoreContribution": 40 },
    { "id": "validar-firma", "pluginId": "signature", "status": "COMPLETED", "passed": false, "match": 0, "scoreContribution": 0 }
  ]
}

11Consultar una ejecución del workflow

Consulta el estado y la salida de una ejecución asincrónica usando el executionId recibido al iniciar el workflow. No recibe body.

GET /api/workflow-executions/{executionId}
GET /api/workflow-executions/{executionId}
Authorization: Bearer {ACCESS_TOKEN}

Campos

CampoTipoObligatorioDescripción
executionIdRutaIdentificador entregado al crear la ejecución.

Comportamiento

Los estados propuestos son QUEUED → RUNNING → COMPLETED (o FAILED). COMPLETED significa que el motor terminó técnicamente; la decisión funcional está en decision.passed.

Respuesta de ejemplo

200 · JSON
{
  "executionId": "exe_01K1T9B8MZWR",
  "workflowId": "validacion-contrato",
  "workflowVersion": 3,
  "definitionHash": "sha256:5d322e...",
  "status": "COMPLETED",
  "decision": { "passed": false, "score": 40, "minScore": 80 },
  "steps": [
    { "id": "validar-qr", "pluginId": "qr", "status": "COMPLETED", "passed": true, "match": 100, "scoreContribution": 40 },
    { "id": "validar-firma", "pluginId": "signature", "status": "COMPLETED", "passed": false, "match": 0, "scoreContribution": 0 }
  ]
}

HTTPErrores

CódigoSignificado
401 UnauthorizedFalta el token o expiró, firma o emisor no válidos, no es un access token, client_id no permitido, o un cliente técnico sin el scope mira-api/execute.
403 ForbiddenToken válido, pero un usuario humano no pertenece a MIRA_ADMIN/MIRA_STANDARD, o el plugin solicitado está deshabilitado.
409 ConflictYa existe una versión más nueva del workflow, o se reutilizó un Idempotency-Key con contenido distinto.
500 Internal Server ErrorError inesperado de procesamiento, p.ej. una página superior al total del PDF en FACE.
504 Gateway TimeoutUn workflow síncrono superó timeoutSeconds (código WORKFLOW_TIMEOUT).
Agendar demo