Microsoft Power Automate Integration
Erstellen Sie Low-Code-Flows mit einem benutzerdefinierten Certyo-Connector, der bei Dynamics-365-Aenderungen, SharePoint-Uploads und SQL-Ereignissen ausgeloest wird, um Datensaetze auf der Blockchain zu verankern.
Ueberblick
Microsoft Power Automate ermoeglicht Citizen Developers und Integrationsteams, Certyo mit ueber 1.000 Microsoft- und Drittanbieterdiensten ueber einen visuellen Flow-Builder zu verbinden. Dieser Leitfaden behandelt die Erstellung eines benutzerdefinierten Certyo-Connectors aus einer OpenAPI-Definition und den Aufbau von drei produktionsreifen Flow-Vorlagen.
Der benutzerdefinierte Connector kapselt die Certyo REST API als erstklassige Power-Platform-Ressource und gibt Flow-Autoren Zugriff auf Datensatz-Ingestion, Massenoperationen und Verifikation ohne Code zu schreiben.
Voraussetzungen
- Power Automate Premium (15 $/Benutzer/Monat) — erforderlich fuer benutzerdefinierte Connectors und Premium-Trigger
- Certyo API-Schluessel (erhalten Sie im Schnellstart-Leitfaden)
- Zugriff auf das Power Platform Admin Center fuer die Connector-Registrierung
- Azure Active Directory-Tenant (fuer die Einrichtung der Connector-Authentifizierung)
- Zugriff auf das Quellsystem: Dynamics 365, SharePoint oder Azure SQL je nach Flow
Architektur
┌──────────────────────────────────────────────────────────────────┐
│ 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 │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘Einrichtung des benutzerdefinierten Connectors
Benutzerdefinierte Power-Automate-Connectors werden aus einer OpenAPI-(Swagger-)Spezifikation definiert. Befolgen Sie diese Schritte, um den Certyo-Connector in Ihrer Power-Platform-Umgebung zu registrieren.
Schritt 1: Connector erstellen
- Gehen Sie zu Power Automate > Daten > Benutzerdefinierte Connectors > Neuer benutzerdefinierter Connector > OpenAPI von URL importieren
- Geben Sie einen Namen ein:
Certyo Records API - Fuegen Sie die URL Ihrer gehosteten OpenAPI-Spezifikation ein oder laden Sie die JSON-Definition unten hoch
Schritt 2: Authentifizierung konfigurieren
- Auf der Registerkarte Sicherheit waehlen Sie API Key
- Parameterbeschriftung:
API Key - Parametername:
X-API-Key - Parameterstandort: Header
Schritt 3: Connector testen
- Erstellen Sie eine neue Verbindung mit Ihrem Certyo API-Schluessel
- Waehlen Sie die Operation IngestRecord aus
- Geben Sie Testwerte ein und ueberpruefen Sie, ob Sie eine
202 Accepted-Antwort erhalten
Codebeispiele
{
"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
}Flow-Vorlagen
Nachfolgend finden Sie drei produktionsreife Flow-Muster. Jedes kann im visuellen Power-Automate-Designer erstellt oder als JSON-Definition importiert werden.
Flow 1: Dynamics 365 Datensatzaenderung
Wird ausgeloest, wenn eine Verkaufsauftragszeile in Dataverse geaendert wird. Der Flow erstellt einen Certyo-Datensatz, nimmt ihn auf und schreibt den recordHash in eine benutzerdefinierte Spalte der D365-Entitaet fuer Nachverfolgbarkeit zurueck.
- Trigger: Wenn eine Zeile hinzugefuegt oder geaendert wird (Dataverse-Connector)
- Filter:
statecode eq 1(nur bestaetigte Auftraege) - Aktion 1: Compose — Certyo-Datensatz-JSON aus Trigger-Outputs erstellen
- Aktion 2: Certyo Custom Connector —
IngestRecord - Aktion 3: Zeile aktualisieren —
recordHashundacceptedAtin D365 zurueckschreiben - Fehlerpfad: Bei Fehler Fehlerdetails fuer die Ueberwachung zusammenstellen
Flow 2: SharePoint Dokument-Upload
Wird ausgeloest, wenn ein Dokument in eine SharePoint-Bibliothek hochgeladen wird. Der Flow extrahiert Dokumentmetadaten und Content-Hash und nimmt sie in Certyo zur Dokumentauthentizitaetsverfolgung auf.
- Trigger: Wenn eine Datei erstellt wird (SharePoint-Connector)
- Aktion 1: Dateieigenschaften abrufen — Dokumentmetadaten lesen
- Aktion 2: Dateiinhalt abrufen — SHA-256 Hash der Datei berechnen
- Aktion 3: Benutzerdefinierter Certyo-Connector —
IngestRecordmit Dokumentmetadaten und Content-Hash inrecordPayload - Aktion 4: Dateieigenschaften aktualisieren — Certyo
recordHashin einer benutzerdefinierten SharePoint-Spalte speichern
Flow 3: Geplante Verifikation
Laeuft nach Zeitplan (z.B. taeglich), um zu ueberpruefen, ob kuerzlich aufgenommene Datensaetze erfolgreich auf der Blockchain verankert wurden.
- Trigger: Wiederholung — alle 24 Stunden
- Aktion 1: Benutzerdefinierter Certyo-Connector —
QueryRecordsmittenantId-Filter - Aktion 2: Auf jedes anwenden — ueber Datensaetze mit Status iterieren
Batched - Aktion 3: Benutzerdefinierter Certyo-Connector —
VerifyRecordfuer jeden - Aktion 4: Bedingung — wenn die Verifikation fehlschlaegt, eine Alarm-E-Mail ueber den Outlook 365 Connector senden
Authentifizierung
Der benutzerdefinierte Connector verwendet API Key-Authentifizierung. Wenn ein Benutzer eine Verbindung zum Certyo-Connector in Power Automate erstellt, gibt er seinen Certyo API-Schluessel einmalig ein. Die Plattform speichert ihn sicher und fuegt ihn als X-API-Key -Header an jede Anfrage an.
- Verbindungen pro Benutzer: Jeder Flow-Autor erstellt seine eigene Verbindung mit seinem API-Schluessel. Dies ermoeglicht benutzerspezifische Audit-Trails in Certyo.
- Dienstkonto-Verbindung: Fuer automatisierte Flows (geplant, ereignisgesteuert) verwenden Sie einen dedizierten Certyo-Dienstkonto-API-Schluessel. Teilen Sie die Verbindung mit den Flow-Eigentuemern.
- Schluesselrotation: Aktualisieren Sie bei der Schluesselrotation die Verbindung unter Power Automate > Daten > Verbindungen. Aktive Flows uebernehmen den neuen Schluessel automatisch.
Connector-Zertifizierung
Um den Certyo-Connector im oeffentlichen Power Platform Connector-Katalog verfuegbar zu machen (sichtbar fuer alle Power Automate-Benutzer weltweit), folgen Sie dem Microsoft-Zertifizierungsprozess:
- Zur Pruefung einreichen: Verwenden Sie den
paconn submit-CLI-Befehl des Microsoft Power Platform Connectors SDK - Dokumentation: Stellen Sie eine Connector-README, ein Icon (160x160 PNG) und Beschreibungen der Verbindungsparameter bereit
- Testen: Microsoft erfordert funktionierende Testanmeldeinformationen und einen Demo-Flow zur Validierung
- SLA: Der Connector muss die API-Zuverlaessigkeitsanforderungen von Microsoft erfuellen (99,9% Verfuegbarkeit, Antwortzeiten unter 3 Sekunden)
- Zeitrahmen: Die Zertifizierung dauert typischerweise 2-4 Wochen nach der Einreichung
Drosselung und Limits
Power Automate setzt Ausfuehrungslimits durch, die das Design Ihrer Certyo-Integrationsflows beeinflussen:
- 600 Aktionen pro Flow-Ausfuehrung — Eine Flow-Ausfuehrung, die 500 Datensaetze in einer "Auf jedes anwenden"-Schleife verarbeitet, verwendet mindestens 500 Aktionen (eine pro Iteration) plus Setup-Aktionen. Bleiben Sie unter dem Limit oder teilen Sie in Teil-Flows auf.
- 100.000 Aktionen pro 24 Stunden — Taegliches Limit pro Benutzer ueber alle Flows. Aufnahme mit hohem Volumen sollte die
BulkIngestRecords-Operation verwenden, um bis zu 1.000 Datensaetze pro Aktion zu stapeln. - Connector-Parallelitaet: Benutzerdefinierte Connectors haben standardmaessig 1 gleichzeitige Anfrage. Erhoehen Sie dies ueber die Registerkarte "Allgemein" im Connector-Editor auf maximal 50 gleichzeitige Verbindungen.
- Retry-Richtlinie: Power Automate wiederholt fehlgeschlagene HTTP-Aktionen bis zu 4 Mal mit exponentiellem Backoff. Certyos
idempotencyKeygewaehrleistet sichere Wiederholungen.
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
- Authentifizierung — Benutzerdefinierter Connector mit API Key-Authentifizierung und Premium-Stufen-Setup
- Architektur — D365/SharePoint/SQL-Trigger → Benutzerdefinierter Certyo-Connector → Records API
- Connector-Spezifikation — OpenAPI 3.0 Definition zum Import in Power Platform
- Flow-Vorlagen — D365 Datensatzaenderung, SharePoint Dokument-Upload, geplante Verifikation
- Zertifizierung — Weg zum Microsoft-zertifizierten Connector fuer den oeffentlichen Katalog
- Drosselung — 600 Aktionen/Flow/Ausfuehrung-Limits und effiziente Flow-Designmuster
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 "Generieren Sie einen Power-Automate-Flow, der D365-Datensatzaenderungen an Certyo sendet"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,
generieren sie einen power-automate-flow, der d365-datensatzaenderungen an certyo sendet"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