Constaia
Integraciones

Power Automate

Valida documentos de SharePoint u OneDrive con la acción HTTP de Power Automate, analiza la respuesta con Parse JSON y recibe eventos de Constaia.

En Power Automate llamas a Constaia con la acción HTTP, enviando el fichero en base64 dentro de un cuerpo JSON. La respuesta se lee con Parse JSON y se reparte con un Switch según el veredicto. Para recibir eventos asíncronos usas el desencadenador When a HTTP request is received.

La acción HTTP y el desencadenador When a HTTP request is received son conectores premium: necesitas una licencia de Power Automate que los incluya.

Requisitos

  • Power Automate con acceso a conectores premium.
  • Una clave de test ck_test_… del panel. Consulta Autenticación.
  • Un origen del documento. En esta guía: SharePoint, con el desencadenador When a file is created in a folder (properties only) seguido de Get file content. Con OneDrive o un adjunto de Outlook es igual: solo cambia de dónde sale el contenido del fichero.

Analizar un documento

Obtén el contenido del fichero

Después del desencadenador, añade SharePoint → Get file content con File Identifier igual al Identifier del desencadenador. La acción se llamará Get_file_content en las expresiones.

Añade la acción HTTP

CampoValor
MethodPOST
URIhttps://api.constaia.com/v1/analyze
HeadersAuthorization: Bearer ck_test_… · Content-Type: application/json · Idempotency-Key: @{workflow()?['run']?['name']}

Y como Body:

Body
{
  "file_base64": "@{base64(body('Get_file_content'))}",
  "filename": "@{triggerOutputs()?['body/{FilenameWithExtension}']}",
  "options": {
    "expect": "invoice",
    "export": ["xlsx"],
    "language": "es",
    "metadata": { "source": "power-automate" }
  }
}

La cabecera Idempotency-Key usa el identificador de la ejecución: si la acción HTTP reintenta por su política de reintentos, Constaia devuelve la respuesta guardada sin cobrar dos veces. Más en Idempotencia. Las opciones están en POST /v1/analyze.

Comprueba el código de estado

Si el análisis no termina en 30 s (PDFs largos), la API responde 202 con status: "queued" o "processing" y sin veredicto. Añade una Condition con @{outputs('HTTP')?['statusCode']} igual a 200 antes de seguir, o usa "async": true y recibe el resultado por webhook (más abajo).

Los errores (4xx, 5xx) hacen fallar la acción HTTP. Para tratarlos, añade una rama con Configure run after → has failed y lee body('HTTP')?['error']?['code'] y body('HTTP')?['error']?['request_id']. Los códigos están en Errores.

Analiza la respuesta con Parse JSON

Añade Parse JSON con Content @{body('HTTP')} y este esquema (solo la parte que usas; las propiedades que no declares siguen disponibles en body('HTTP')):

Schema
{
  "type": "object",
  "properties": {
    "id": { "type": "string" },
    "status": { "type": "string" },
    "document": {
      "type": ["object", "null"],
      "properties": {
        "type": { "type": "string" },
        "label": { "type": "string" },
        "confidence": { "type": "number" }
      }
    },
    "verdict": {
      "type": ["object", "null"],
      "properties": {
        "status": { "type": "string" },
        "reasons": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "severity": { "type": "string" },
              "message": { "type": "string" }
            }
          }
        }
      }
    },
    "fields": { "type": "object" },
    "warnings": { "type": "array", "items": { "type": "string" } },
    "exports": { "type": "object" }
  }
}

Enruta con un Switch

Añade un Switch sobre @{body('Parse_JSON')?['verdict']?['status']} con tres casos:

CasoQué hacer
Válido validGuardar los datos. Por ejemplo, el total: @{body('Parse_JSON')?['fields']?['total']?['value']}; el Excel generado: @{body('Parse_JSON')?['exports']?['xlsx']} (URL firmada, válida 24 h).
No válido invalidAvisar por Teams o correo con los message de verdict.reasons.
Revisar reviewCrear una tarea o una aprobación para una persona. Ver Revisión humana.

Cada campo extraído es un objeto con value, confidence, validated y source. Más en Veredictos y Exportaciones.

Probar en modo test

Con una clave ck_test_… no se consumen créditos y la respuesta depende del nombre del fichero que envías en filename (el contenido tiene que ser un JPEG, PNG, WEBP, HEIC o PDF real). Sube a la carpeta ficheros llamados:

FicheroCon expectResultado
invoice.pdfinvoiceVálido factura con base 100, IVA 21 %, total 121 EUR
dni_expired.jpges_dniNo válido not_expired con severidad error
blurry.jpges_dniRevisar low_quality con severidad warning

Mientras pruebas, también puedes fijar filename a mano en el cuerpo. Todos los escenarios en Modo test.

Recibir eventos por webhook

Crea el flujo receptor

Crea un flujo con el desencadenador When a HTTP request is received. En Who can trigger the flow? elige Anyone (Constaia no se autentica en Microsoft Entra) y usa como Request Body JSON Schema:

Request Body JSON Schema
{
  "type": "object",
  "properties": {
    "type": { "type": "string" },
    "created_at": { "type": "string" },
    "data": { "type": "object", "properties": { "id": { "type": "string" } } }
  }
}

Guarda el flujo, copia la URL generada y regístrala en el panel o con POST /v1/webhook-endpoints (ver Webhooks). Si el flujo no tiene una acción Response, el desencadenador responde 202 Accepted de inmediato, lo que Constaia cuenta como entrega correcta.

Vuelve a leer el análisis

Power Automate no tiene una función para calcular el HMAC-SHA256 de la firma, así que no te fíes del cuerpo del evento:

  1. Condition: @{startsWith(triggerBody()?['data']?['id'], 'an_')} es true.
  2. HTTP GET a https://api.constaia.com/v1/analyses/@{triggerBody()?['data']?['id']} con la cabecera Authorization.
  3. Parse JSON con el esquema de arriba y el mismo Switch.

La API solo devuelve análisis de tu cuenta: un evento falsificado como mucho te hace releer un análisis tuyo. Para batch.completed, data.id empieza por bat_ y la lectura es GET /v1/batches/{id}.

Descarta duplicados

Constaia reintenta las entregas fallidas durante unos 3 días con el mismo webhook-id, disponible en @{triggerOutputs()?['headers']?['webhook-id']}. Guárdalo (por ejemplo, en una lista de SharePoint o una tabla de Dataverse) y termina el flujo si ya existe.

La relectura necesita que el análisis siga guardado: no uses keep_results: false en los análisis que quieras recibir por webhook.

Seguridad

  • No escribas una clave ck_live_… en flujos que compartas o exportes. Si trabajas con soluciones, guarda la clave en una variable de entorno de tipo Secret (respaldada por Azure Key Vault) y úsala en la cabecera.
  • Activa Settings → Secure inputs y Secure outputs en las acciones HTTP: así la clave, el documento en base64 y los datos extraídos no se muestran en el historial de ejecuciones.
  • Usa una clave de test mientras montas el flujo y la live solo al activarlo.
  • Constaia borra el fichero al terminar con storage: "none" (por defecto). Más en Almacenamiento y privacidad.

Límites

  • 20 MB por fichero (en base64 el cuerpo crece aproximadamente un 33 %); PDFs de hasta 30 páginas en síncrono y hasta 200 con async: true.
  • 2 peticiones por segundo por clave en el plan gratuito (10 en el de pago). Si recorres muchos ficheros con Apply to each, limita su concurrencia en la configuración de la acción; ante un 429 la API envía Retry-After. Ver Límites de uso.

Siguientes pasos

En esta página