Integración con Microsoft Power Automate
Construye flujos low-code con un conector personalizado de Certyo que se activa con cambios en Dynamics 365, subidas a SharePoint y eventos SQL para anclar registros en la blockchain.
Descripción general
Microsoft Power Automate permite a desarrolladores ciudadanos y equipos de integración conectar Certyo con más de 1.000 servicios de Microsoft y terceros usando un constructor visual de flujos. Esta guía cubre la creación de un conector personalizado de Certyo desde una definición OpenAPI y la construcción de tres plantillas de flujo listas para producción.
El conector personalizado envuelve el REST API de Certyo como un recurso de primera clase de Power Platform, dando a los autores de flujos acceso a la ingesta de registros, operaciones en lote y verificación sin escribir código.
Requisitos previos
- Power Automate Premium ($15/usuario/mes) — requerido para conectores personalizados y triggers premium
- Clave API de Certyo (obtener de la Guía de inicio rápido)
- Acceso al centro de administración de Power Platform para el registro del conector
- Tenant de Azure Active Directory (para la configuración de autenticación del conector)
- Acceso al sistema fuente: Dynamics 365, SharePoint o Azure SQL según tu flujo
Arquitectura
┌──────────────────────────────────────────────────────────────────┐
│ TRIGGER SOURCES │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────────────┐ │
│ │ Dynamics 365 │ │ SharePoint │ │ Azure SQL / SQL │ │
│ │ Dataverse │ │ Document │ │ Server Change │ │
│ │ Row Changed │ │ Uploaded │ │ Tracking │ │
│ └──────┬───────┘ └──────┬───────┘ └────────────┬───────────┘ │
│ └─────────────────┼───────────────────────┘ │
├───────────────────────────┼──────────────────────────────────────┤
│ POWER AUTOMATE FLOW │
│ ┌────────────────────────┴────────────────────────────────┐ │
│ │ 1. Trigger fires on source system event │ │
│ │ 2. Compose: build Certyo record JSON │ │
│ │ 3. Custom Connector: POST /api/v1/records │ │
│ │ 4. Condition: check 202 Accepted │ │
│ │ 5. Update source record with recordHash │ │
│ └────────────────────────┬────────────────────────────────┘ │
├───────────────────────────┼──────────────────────────────────────┤
│ CERTYO PIPELINE │
│ ┌────────────────────────┴────────────────────────────────┐ │
│ │ POST /api/v1/records ──► 202 Accepted + recordHash │ │
│ │ │ │ │
│ │ Kafka topic ──► Accumulate ──► Merkle tree │ │
│ │ ──► IPFS pin ──► Polygon anchor │ │
│ │ │ │
│ │ ~60-90 seconds to on-chain confirmation │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘Configuración del conector personalizado
Los conectores personalizados de Power Automate se definen desde una especificación OpenAPI (Swagger). Sigue estos pasos para registrar el conector de Certyo en tu entorno de Power Platform.
Paso 1: Crear el conector
- Ve a Power Automate > Datos > Conectores personalizados > Nuevo conector personalizado > Importar un OpenAPI desde URL
- Introduce un nombre:
Certyo Records API - Pega la URL de tu especificación OpenAPI alojada, o sube la definición JSON a continuación
Paso 2: Configurar autenticación
- En la pestaña Seguridad , selecciona API Key
- Etiqueta del parámetro:
API Key - Nombre del parámetro:
X-API-Key - Ubicación del parámetro: Header
Paso 3: Probar el conector
- Crea una nueva conexión usando tu clave API de Certyo
- Selecciona la operación IngestRecord
- Rellena valores de prueba y verifica que recibes una respuesta
202 Accepted
Ejemplos de código
{
"openapi": "3.0.1",
"info": {
"title": "Certyo Records API",
"description": "Blockchain-backed record ingestion, verification, and query for the Certyo durable records platform.",
"version": "1.0.0",
"contact": {
"name": "Certyo Developer Support",
"url": "https://www.certyos.com/developers"
}
},
"servers": [
{
"url": "https://www.certyos.com"
}
],
"security": [
{
"ApiKeyAuth": []
}
],
"paths": {
"/api/v1/records": {
"post": {
"operationId": "IngestRecord",
"summary": "Ingest a single record for blockchain anchoring",
"description": "Accepts a record and returns 202 with a record hash. The record flows through the accumulation pipeline and is anchored on Polygon within ~60-90 seconds.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IngestRecordRequest"
}
}
}
},
"responses": {
"202": {
"description": "Record accepted for processing",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IngestRecordResponse"
}
}
}
}
}
},
"get": {
"operationId": "QueryRecords",
"summary": "Query records by tenant and record ID",
"parameters": [
{
"name": "tenantId",
"in": "query",
"required": true,
"schema": { "type": "string" }
},
{
"name": "recordId",
"in": "query",
"required": false,
"schema": { "type": "string" }
}
],
"responses": {
"200": {
"description": "Matching records"
}
}
}
},
"/api/v1/records/bulk": {
"post": {
"operationId": "BulkIngestRecords",
"summary": "Ingest up to 1000 records in a single request",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BulkIngestRequest"
}
}
}
},
"responses": {
"202": {
"description": "Bulk records accepted"
}
}
}
},
"/api/v1/verify/record": {
"post": {
"operationId": "VerifyRecord",
"summary": "Verify a record against its on-chain Merkle proof",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VerifyRecordRequest"
}
}
}
},
"responses": {
"200": {
"description": "Verification result"
}
}
}
}
},
"components": {
"securitySchemes": {
"ApiKeyAuth": {
"type": "apiKey",
"name": "X-API-Key",
"in": "header"
}
},
"schemas": {
"IngestRecordRequest": {
"type": "object",
"required": ["tenantId", "database", "collection", "recordId", "recordPayload"],
"properties": {
"tenantId": { "type": "string", "description": "Your tenant identifier" },
"database": { "type": "string", "description": "Logical source database or system" },
"collection": { "type": "string", "description": "Logical table or collection" },
"recordId": { "type": "string", "description": "Unique record identifier" },
"recordVersion": { "type": "string", "default": "1" },
"operationType": { "type": "string", "enum": ["insert", "update", "delete", "upsert"], "default": "upsert" },
"recordPayload": { "type": "object", "description": "The record data as arbitrary JSON" },
"sourceTimestamp": { "type": "string", "format": "date-time" },
"idempotencyKey": { "type": "string", "description": "Deduplication key (24h window)" }
}
},
"IngestRecordResponse": {
"type": "object",
"properties": {
"recordId": { "type": "string" },
"recordHash": { "type": "string" },
"tenantId": { "type": "string" },
"acceptedAt": { "type": "string", "format": "date-time" },
"idempotencyReplayed": { "type": "boolean" }
}
},
"BulkIngestRequest": {
"type": "object",
"required": ["tenantId", "records"],
"properties": {
"tenantId": { "type": "string" },
"records": {
"type": "array",
"maxItems": 1000,
"items": { "$ref": "#/components/schemas/IngestRecordRequest" }
}
}
},
"VerifyRecordRequest": {
"type": "object",
"required": ["tenantId", "database", "collection", "recordId", "payload"],
"properties": {
"tenantId": { "type": "string" },
"database": { "type": "string" },
"collection": { "type": "string" },
"recordId": { "type": "string" },
"payload": { "type": "object" }
}
}
}
}
}{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"triggers": {
"When_a_row_is_added_or_modified": {
"type": "OpenApiConnectionWebhook",
"inputs": {
"host": {
"connectionName": "shared_commondataserviceforapps",
"operationId": "SubscribeWebhookTrigger",
"apiId": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps"
},
"parameters": {
"subscriptionRequest/message": 4,
"subscriptionRequest/entityname": "salesorder",
"subscriptionRequest/scope": 4,
"subscriptionRequest/filterexpression": "statecode eq 1"
}
}
}
},
"actions": {
"Compose_Certyo_Record": {
"type": "Compose",
"inputs": {
"tenantId": "@{parameters('CertyoTenantId')}",
"database": "dynamics-365",
"collection": "sales-orders",
"recordId": "@{triggerOutputs()?['body/salesorderid']}",
"recordVersion": "@{triggerOutputs()?['body/versionnumber']}",
"operationType": "upsert",
"recordPayload": {
"orderId": "@{triggerOutputs()?['body/salesorderid']}",
"orderNumber": "@{triggerOutputs()?['body/ordernumber']}",
"customerId": "@{triggerOutputs()?['body/_customerid_value']}",
"totalAmount": "@{triggerOutputs()?['body/totalamount']}",
"currency": "@{triggerOutputs()?['body/transactioncurrencyid']}",
"status": "@{triggerOutputs()?['body/statuscode']}",
"createdOn": "@{triggerOutputs()?['body/createdon']}",
"modifiedOn": "@{triggerOutputs()?['body/modifiedon']}"
},
"sourceTimestamp": "@{triggerOutputs()?['body/modifiedon']}",
"idempotencyKey": "@{triggerOutputs()?['body/salesorderid']}-@{triggerOutputs()?['body/versionnumber']}-@{utcNow('yyyy-MM-dd')}"
},
"runAfter": {}
},
"Ingest_Record_to_Certyo": {
"type": "OpenApiConnection",
"inputs": {
"host": {
"connectionName": "shared_certyo-records-api",
"operationId": "IngestRecord",
"apiId": "/providers/Microsoft.PowerApps/apis/shared_certyo-records-api"
},
"parameters": {
"body": "@outputs('Compose_Certyo_Record')"
}
},
"runAfter": {
"Compose_Certyo_Record": ["Succeeded"]
}
},
"Update_D365_with_Hash": {
"type": "OpenApiConnection",
"inputs": {
"host": {
"connectionName": "shared_commondataserviceforapps",
"operationId": "UpdateRecord",
"apiId": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps"
},
"parameters": {
"entityName": "salesorders",
"recordId": "@{triggerOutputs()?['body/salesorderid']}",
"item/cr_certyorecordhash": "@{body('Ingest_Record_to_Certyo')?['recordHash']}",
"item/cr_certyoacceptedat": "@{body('Ingest_Record_to_Certyo')?['acceptedAt']}"
}
},
"runAfter": {
"Ingest_Record_to_Certyo": ["Succeeded"]
}
},
"Handle_Failure": {
"type": "Compose",
"inputs": {
"error": "Certyo ingestion failed",
"orderId": "@{triggerOutputs()?['body/salesorderid']}",
"statusCode": "@{outputs('Ingest_Record_to_Certyo')['statusCode']}",
"timestamp": "@{utcNow()}"
},
"runAfter": {
"Ingest_Record_to_Certyo": ["Failed", "TimedOut"]
}
}
},
"parameters": {
"CertyoTenantId": {
"type": "string",
"defaultValue": "acme-corp"
}
}
}
}using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
namespace Certyo.PowerAutomate.Bridge;
/// <summary>
/// Azure Function that acts as a bridge between Power Automate and Certyo
/// for complex transformation scenarios that exceed Power Automate's
/// expression capabilities (nested loops, conditional mappings, etc.).
/// </summary>
public class CertyoBridge
{
private readonly HttpClient _http;
private readonly ILogger<CertyoBridge> _logger;
private readonly string _certyoApiKey;
private readonly string _certyoBaseUrl;
public CertyoBridge(
IHttpClientFactory httpFactory,
ILogger<CertyoBridge> logger)
{
_http = httpFactory.CreateClient("Certyo");
_logger = logger;
_certyoApiKey = Environment.GetEnvironmentVariable("CERTYO_API_KEY")
?? throw new InvalidOperationException("CERTYO_API_KEY not set");
_certyoBaseUrl = Environment.GetEnvironmentVariable("CERTYO_BASE_URL")
?? "https://www.certyos.com";
}
[Function("TransformAndIngest")]
public async Task<HttpResponseData> TransformAndIngest(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
{
var input = await req.ReadFromJsonAsync<SourceRecord>();
if (input is null)
{
var bad = req.CreateResponse(HttpStatusCode.BadRequest);
await bad.WriteAsJsonAsync(new { error = "Invalid request body" });
return bad;
}
// Transform SharePoint document metadata to Certyo record
var certyoRecord = new CertyoRecord
{
TenantId = Environment.GetEnvironmentVariable("CERTYO_TENANT_ID")
?? "acme-corp",
Database = "sharepoint",
Collection = input.LibraryName ?? "documents",
RecordId = input.DocumentId,
RecordVersion = input.Version?.ToString() ?? "1",
OperationType = input.IsNew ? "insert" : "upsert",
RecordPayload = new Dictionary<string, object?>
{
["documentId"] = input.DocumentId,
["fileName"] = input.FileName,
["fileSize"] = input.FileSize,
["contentHash"] = input.ContentHash,
["libraryName"] = input.LibraryName,
["author"] = input.Author,
["modifiedBy"] = input.ModifiedBy,
["metadata"] = input.CustomMetadata
},
SourceTimestamp = input.ModifiedAt ?? DateTime.UtcNow,
IdempotencyKey = $"{input.DocumentId}-{input.Version}-"
+ $"{DateTime.UtcNow:yyyy-MM-dd}"
};
// Call Certyo API
using var request = new HttpRequestMessage(
HttpMethod.Post,
$"{_certyoBaseUrl}/api/v1/records");
request.Headers.Add("X-API-Key", _certyoApiKey);
request.Content = JsonContent.Create(certyoRecord);
var certyoResponse = await _http.SendAsync(request);
if (!certyoResponse.IsSuccessStatusCode)
{
_logger.LogError(
"Certyo ingestion failed: {Status} for doc {DocId}",
certyoResponse.StatusCode, input.DocumentId);
var errorResp = req.CreateResponse(certyoResponse.StatusCode);
await errorResp.WriteAsJsonAsync(new
{
error = "Certyo ingestion failed",
status = (int)certyoResponse.StatusCode,
documentId = input.DocumentId
});
return errorResp;
}
var result = await certyoResponse.Content
.ReadFromJsonAsync<IngestResponse>();
_logger.LogInformation(
"Record ingested: {Hash} for doc {DocId}",
result?.RecordHash, input.DocumentId);
var response = req.CreateResponse(HttpStatusCode.Accepted);
await response.WriteAsJsonAsync(result);
return response;
}
[Function("VerifyRecord")]
public async Task<HttpResponseData> VerifyRecord(
[HttpTrigger(AuthorizationLevel.Function, "post",
Route = "verify")] HttpRequestData req)
{
var input = await req.ReadFromJsonAsync<VerifyRequest>();
if (input is null)
{
var bad = req.CreateResponse(HttpStatusCode.BadRequest);
await bad.WriteAsJsonAsync(new { error = "Invalid request" });
return bad;
}
using var request = new HttpRequestMessage(
HttpMethod.Post,
$"{_certyoBaseUrl}/api/v1/verify/record");
request.Headers.Add("X-API-Key", _certyoApiKey);
request.Content = JsonContent.Create(input);
var certyoResponse = await _http.SendAsync(request);
var result = await certyoResponse.Content.ReadAsStringAsync();
var response = req.CreateResponse(certyoResponse.StatusCode);
response.Headers.Add("Content-Type", "application/json");
await response.WriteStringAsync(result);
return response;
}
}
public record SourceRecord
{
public string DocumentId { get; init; } = "";
public string? FileName { get; init; }
public long? FileSize { get; init; }
public string? ContentHash { get; init; }
public string? LibraryName { get; init; }
public string? Author { get; init; }
public string? ModifiedBy { get; init; }
public int? Version { get; init; }
public bool IsNew { get; init; }
public DateTime? ModifiedAt { get; init; }
public Dictionary<string, object?>? CustomMetadata { get; init; }
}
public record CertyoRecord
{
[JsonPropertyName("tenantId")] public string TenantId { get; init; } = "";
[JsonPropertyName("database")] public string Database { get; init; } = "";
[JsonPropertyName("collection")] public string Collection { get; init; } = "";
[JsonPropertyName("recordId")] public string RecordId { get; init; } = "";
[JsonPropertyName("recordVersion")] public string RecordVersion { get; init; } = "1";
[JsonPropertyName("operationType")] public string OperationType { get; init; } = "upsert";
[JsonPropertyName("recordPayload")] public Dictionary<string, object?> RecordPayload { get; init; } = new();
[JsonPropertyName("sourceTimestamp")] public DateTime SourceTimestamp { get; init; }
[JsonPropertyName("idempotencyKey")] public string IdempotencyKey { get; init; } = "";
}
public record IngestResponse
{
[JsonPropertyName("recordId")] public string RecordId { get; init; } = "";
[JsonPropertyName("recordHash")] public string RecordHash { get; init; } = "";
[JsonPropertyName("tenantId")] public string TenantId { get; init; } = "";
[JsonPropertyName("acceptedAt")] public DateTime AcceptedAt { get; init; }
[JsonPropertyName("idempotencyReplayed")] public bool IdempotencyReplayed { get; init; }
}
public record VerifyRequest
{
[JsonPropertyName("tenantId")] public string TenantId { get; init; } = "";
[JsonPropertyName("database")] public string Database { get; init; } = "";
[JsonPropertyName("collection")] public string Collection { get; init; } = "";
[JsonPropertyName("recordId")] public string RecordId { get; init; } = "";
[JsonPropertyName("payload")] public object? Payload { get; init; }
}#!/usr/bin/env pwsh
<#
.SYNOPSIS
Deploys the Certyo custom connector to a Power Platform environment.
.DESCRIPTION
Imports the OpenAPI definition, configures API Key authentication,
and creates a connection for the specified environment.
.PARAMETER EnvironmentId
Power Platform environment ID (GUID).
.PARAMETER OpenApiPath
Path to the certyo-connector-openapi.json file.
.PARAMETER CertyoApiKey
Certyo API key to configure on the connection.
#>
param(
[Parameter(Mandatory)]
[string]$EnvironmentId,
[Parameter(Mandatory)]
[string]$OpenApiPath,
[Parameter(Mandatory)]
[string]$CertyoApiKey
)
$ErrorActionPreference = "Stop"
# Ensure Power Apps admin module is installed
if (-not (Get-Module -ListAvailable -Name Microsoft.PowerApps.Administration.PowerShell)) {
Write-Host "Installing Power Apps admin module..."
Install-Module -Name Microsoft.PowerApps.Administration.PowerShell -Scope CurrentUser -Force
}
Import-Module Microsoft.PowerApps.Administration.PowerShell
# Authenticate to Power Platform
Write-Host "Authenticating to Power Platform..."
Add-PowerAppsAccount
# Read the OpenAPI definition
$openApiContent = Get-Content -Path $OpenApiPath -Raw
$openApiJson = $openApiContent | ConvertFrom-Json
Write-Host "Deploying Certyo connector to environment: $EnvironmentId"
# Create or update the custom connector
$connectorParams = @{
EnvironmentName = $EnvironmentId
ConnectorName = "certyo-records-api"
OpenApiDefinition = $openApiContent
}
try {
# Check if connector already exists
$existing = Get-AdminPowerAppConnector -EnvironmentName $EnvironmentId |
Where-Object { $_.ConnectorName -eq "certyo-records-api" }
if ($existing) {
Write-Host "Updating existing Certyo connector..."
Set-AdminPowerAppConnector @connectorParams
} else {
Write-Host "Creating new Certyo connector..."
New-AdminPowerAppConnector @connectorParams
}
Write-Host "Connector deployed successfully." -ForegroundColor Green
# Create a connection with the API key
Write-Host "Creating connection with API key..."
$connectionParams = @{
ConnectorName = "certyo-records-api"
EnvironmentName = $EnvironmentId
ConnectionParameters = @{
"api_key" = $CertyoApiKey
}
}
New-AdminPowerAppConnection @connectionParams
Write-Host "Connection created successfully." -ForegroundColor Green
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Cyan
Write-Host " 1. Open Power Automate (https://make.powerautomate.com)"
Write-Host " 2. Create a new flow"
Write-Host " 3. Search for 'Certyo Records API' in the connector list"
Write-Host " 4. Use IngestRecord, BulkIngestRecords, or VerifyRecord actions"
} catch {
Write-Error "Deployment failed: $_"
exit 1
}Plantillas de flujo
A continuación se presentan tres patrones de flujo listos para producción. Cada uno puede crearse en el diseñador visual de Power Automate o importarse como una definición JSON.
Flujo 1: Cambio de registro en Dynamics 365
Se activa cuando se modifica una fila de pedido de venta en Dataverse. El flujo compone un registro Certyo, lo ingesta y escribe el recordHash de vuelta en una columna personalizada de la entidad D365 para trazabilidad.
- Trigger: Cuando se agrega o modifica una fila (conector Dataverse)
- Filtro:
statecode eq 1(solo pedidos confirmados) - Acción 1: Compose — construir JSON de registro Certyo desde las salidas del trigger
- Acción 2: Certyo Custom Connector —
IngestRecord - Acción 3: Actualizar fila — escribir
recordHashyacceptedAtde vuelta en D365 - Ruta de error: En caso de fallo, componer detalles del error para monitoreo
Flujo 2: Subida de documento a SharePoint
Se activa cuando un documento se sube a una biblioteca de SharePoint. El flujo extrae metadatos del documento y el hash de contenido, luego los ingesta en Certyo para seguimiento de autenticidad de documentos.
- Trigger: Cuando se crea un archivo (conector SharePoint)
- Acción 1: Obtener propiedades del archivo — recuperar metadatos del documento
- Acción 2: Obtener contenido del archivo — calcular hash SHA-256 del archivo
- Acción 3: Conector personalizado Certyo —
IngestRecordcon metadatos del documento y hash de contenido enrecordPayload - Acción 4: Actualizar propiedades del archivo — almacenar el
recordHashde Certyo en una columna personalizada de SharePoint
Flujo 3: Verificación programada
Se ejecuta según un horario (por ejemplo, diariamente) para verificar que los registros ingestados recientemente se han anclado exitosamente en la blockchain.
- Trigger: Recurrencia — cada 24 horas
- Acción 1: Conector personalizado Certyo —
QueryRecordscon filtrotenantId - Acción 2: Aplicar a cada uno — iterar sobre registros con estado
Batched - Acción 3: Conector personalizado Certyo —
VerifyRecordpara cada uno - Acción 4: Condición — si la verificación falla, enviar un correo de alerta a través del conector Outlook 365
Autenticación
El conector personalizado utiliza autenticación por API Key. Cuando un usuario crea una conexión al conector Certyo en Power Automate, ingresa su clave API de Certyo una vez. La plataforma la almacena de forma segura y la adjunta como el encabezado X-API-Key en cada solicitud.
- Conexiones por usuario: Cada autor de flujo crea su propia conexión con su clave API. Esto permite pistas de auditoría por usuario en Certyo.
- Conexión de cuenta de servicio: Para flujos automatizados (programados, dirigidos por eventos), usa una clave API de cuenta de servicio dedicada de Certyo. Comparte la conexión con los propietarios del flujo.
- Rotación de claves: Al rotar claves API, actualiza la conexión en Power Automate > Datos > Conexiones. Los flujos activos tomarán la nueva clave automáticamente.
Certificación del conector
Para hacer que el conector Certyo esté disponible en la galería pública de conectores de Power Platform (visible para todos los usuarios de Power Automate en todo el mundo), sigue el proceso de certificación de Microsoft:
- Enviar para revisión: Usa el comando CLI
paconn submitdel SDK de Microsoft Power Platform Connectors - Documentación: Proporciona un README del conector, icono (160x160 PNG) y descripciones de parámetros de conexión
- Pruebas: Microsoft requiere credenciales de prueba funcionales y un flujo de demostración para la validación
- SLA: El conector debe cumplir los requisitos de fiabilidad de API de Microsoft (99,9% de disponibilidad, tiempos de respuesta inferiores a 3s)
- Plazo: La certificación normalmente toma de 2 a 4 semanas después del envío
Limitación y límites
Power Automate aplica límites de ejecución que afectan cómo diseñas los flujos de integración con Certyo:
- 600 acciones por ejecución de flujo — Una ejecución de flujo que procesa 500 registros en un bucle "Aplicar a cada uno" usa al menos 500 acciones (una por iteración) más acciones de configuración. Mantente bajo el límite o divide en subflujos.
- 100.000 acciones por 24 horas — Límite diario por usuario en todos los flujos. La ingesta de alto volumen debe usar la operación
BulkIngestRecordspara agrupar hasta 1.000 registros por acción. - Concurrencia del conector: Los conectores personalizados tienen por defecto 1 solicitud concurrente. Aumenta a través de la pestaña General del conector en el editor de conectores personalizados, hasta un máximo de 50 conexiones concurrentes.
- Política de reintentos: Power Automate reintenta acciones HTTP fallidas hasta 4 veces con backoff exponencial. El
idempotencyKeyde Certyo garantiza reintentos seguros.
AI Integration Skill
Download a skill file that enables AI agents to generate working Power Automate + Certyo integration code for any language or framework.
What's inside
- Autenticación — Conector personalizado con autenticación API Key y configuración del nivel Premium
- Arquitectura — Trigger D365/SharePoint/SQL → Conector personalizado Certyo → API de registros
- Especificación del conector — Definición OpenAPI 3.0 para importar en Power Platform
- Plantillas de flujo — Cambio de registro D365, subida de documento SharePoint, verificación programada
- Certificación — Ruta hacia el conector certificado de Microsoft para la galería pública
- Limitación — Límites de 600 acciones/flujo/ejecución y patrones de diseño eficiente de flujos
How to use
Claude Code
Place the file in your project's .claude/commands/ directory, then use it as a slash command:
# Download the skill file
mkdir -p .claude/commands
curl -o .claude/commands/certyo-powerautomate.md \
https://www.certyos.com/developers/skills/certyo-powerautomate-skill.md
# Use it in Claude Code
/certyo-powerautomate "Genera un flujo de Power Automate que envíe cambios de registros D365 a Certyo"Cursor / Copilot / Any AI Agent
Add the file to your project root or attach it to a conversation. The AI agent will use the Power Automate-specific patterns, field mappings, and code examples to generate correct integration code.
# Add to your project
curl -o CERTYO_POWERAUTOMATE.md \
https://www.certyos.com/developers/skills/certyo-powerautomate-skill.md
# Then in your AI agent:
"Using the Certyo Power Automate spec in CERTYO_POWERAUTOMATE.md,
genera un flujo de power automate que envíe cambios de registros d365 a certyo"CLAUDE.md Context File
Append the skill file to your project's CLAUDE.md so every Claude conversation has Power Automate + Certyo context automatically.
# Append to your project's CLAUDE.md
echo "" >> CLAUDE.md
echo "## Certyo Power Automate Integration" >> CLAUDE.md
cat CERTYO_POWERAUTOMATE.md >> CLAUDE.md