Aktionen und Schnittstellen
Kurz gesagt
Ein Aufruf, ein Beleg: st_GenerateDocument erzeugt aus einer Vorlage und einem Datensatz das PDF und gibt es als Base64 zurück. Sie rufen die Aktion aus einem Plugin, aus JavaScript, aus Power Automate oder über die Web-API auf; die Beispiele auf dieser Seite gibt es in C#, JavaScript und HTTP zum Kopieren. Drei Aktionen erzeugen einen Beleg, drei dienen der E-Rechnung, eine hält den Druck schnell, zwei dienen dem KI-Assistenten. Alle sind ungebunden, für jeden sichtbar und ohne eigenes Sicherheitsrecht; Ein- und Ausgaben sind Text, nur st_CheckKeepWarm liefert Ok als Ja/Nein.
Ein PDF in einem Aufruf
POST /api/data/v9.2/st_GenerateDocument
Aktion · ungebunden · ohne eigenes Recht · Ein- und Ausgaben: Text
Sie nennen die Vorlage und den Datensatz und bekommen das PDF zurück. Mehr braucht es nicht:
using System;
using Microsoft.Xrm.Sdk;
public sealed class GenerateDocumentPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var service = ((IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)))
.CreateOrganizationService(context.UserId);
var response = service.Execute(new OrganizationRequest("st_GenerateDocument")
{
["TemplateId"] = "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42", // template id
["PrimaryEntity"] = context.PrimaryEntityName, // e.g. "invoice"
["PrimaryId"] = context.PrimaryEntityId.ToString(),
["Mode"] = "pdf",
["FlowId"] = null // optional: a Power Automate cloud flow to start afterwards
});
var pdfBase64 = (string)response["PdfBase64"]; // the PDF as Base64
var message = (string)response["Message"]; // warnings start with "WARNING:"
}
}// In a form script or a command bar button
async function generateDocument(formContext) {
const response = await Xrm.WebApi.online.execute({
TemplateId: "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42", // template id
PrimaryEntity: formContext.data.entity.getEntityName(), // e.g. "invoice"
PrimaryId: formContext.data.entity.getId().replace(/[{}]/g, ""),
Mode: "pdf",
FlowId: null, // optional: a Power Automate cloud flow to start afterwards
getMetadata: () => ({
boundParameter: null,
operationType: 0, // 0 = action
operationName: "st_GenerateDocument",
parameterTypes: {
TemplateId: { typeName: "Edm.String", structuralProperty: 1 },
PrimaryEntity: { typeName: "Edm.String", structuralProperty: 1 },
PrimaryId: { typeName: "Edm.String", structuralProperty: 1 },
Mode: { typeName: "Edm.String", structuralProperty: 1 },
FlowId: { typeName: "Edm.String", structuralProperty: 1 }
}
})
});
return await response.json(); // .PdfBase64 and .Message
}POST https://contoso.crm4.dynamics.com/api/data/v9.2/st_GenerateDocument HTTP/1.1
Authorization: Bearer <Token>
Content-Type: application/json; charset=utf-8
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
{
"TemplateId": "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42",
"PrimaryEntity": "invoice",
"PrimaryId": "9d4e2b7a-1c3f-4e8d-b2a6-5f7c9e1d3b80",
"Mode": "pdf",
"FlowId": null
}Statt der Kennung können Sie die Vorlage auch als JSON mitgeben (TemplateJson); so arbeitet der Designer. Mit der Eingabe FlowId startet dieselbe Aktion nach dem Beleg einen Flow in Power Automate; im Beispiel steht sie auf null, also ohne Flow (siehe Einen Flow starten). Alle Ein- und Ausgaben stehen unter st_GenerateDocument: alle Ein- und Ausgaben.
Ohne Code
Dasselbe als Button in der Befehlsleiste von Dynamics, ohne eine Zeile eigenen Code: Im Designer legt der Assistent »Buttons in Dynamics verwalten« den Button an, Zweck »Beleg erstellen und anzeigen«. Ein Klick baut den Beleg und öffnet ihn in einem neuen Reiter. Der Button ruft SmartTemplates.Button.showDocument aus st_button.js, für alle angekreuzten Zeilen einer Liste SmartTemplates.Button.showDocumentAll. So geht es: Buttons: der Assistent: Was soll der Button tun? und Button einbauen, ändern, entfernen.
Was zurückkommt
So sieht die Antwort aus, gekürzt:
{
"@odata.context": "https://contoso.crm4.dynamics.com/api/data/v9.2/$metadata#Microsoft.Dynamics.CRM.st_GenerateDocumentResponse",
"PdfBase64": "JVBERi0x…",
"Message": "OK: 2 page(s), 103912 bytes [Server-Daten] · Data: 1 query, 9 column(s), 852 ms · …",
"LayoutJson": "",
"ChoicesJson": "",
"FlowRunId": "",
"TriggerRowId": ""
}
PdfBase64: das PDF als Base64. Es beginnt mitJVBERi0x, also%PDF-1.FileName: der Name des PDF, etwaRechnung_R-2026-0042.pdf(siehe Ausgaben).Message: beginnt bei Erfolg mitOK:und nennt Seiten, Größe und Zeiten. Warnungen beginnen mitWARNING:(siehe Fehler und Warnungen).- Die übrigen Felder bleiben leer, solange Sie keinen anderen
Mode, keine Wahlen und keinen Flow benutzen. Hat die Vorlage eine E-Rechnung »nur XML«, kommenXmlBase64undXmlFileNamedazu (siehe E-Rechnung).
Die Aktionen im Überblick
| Aktion | Was sie tut |
|---|---|
st_GenerateDocument | Erzeugt den Beleg für einen Datensatz und gibt das PDF zurück. |
st_CreateEmail | Erzeugt den Beleg und legt einen E-Mail-Entwurf mit dem PDF als Anhang an. Sendet nicht. |
st_SendEmail | Erzeugt den Beleg und sendet die E-Mail mit Anhang sofort. |
st_GenerateEInvoice | Erzeugt die E-Rechnung eines Datensatzes nur als XML-Datei, bei ZUGFeRD die factur-x.xml. Ohne PDF, ohne Flow. Siehe E-Rechnung. |
st_StandardLesen | Liest die Standards der E-Rechnung: die Liste, die Übersicht eines Standards, seine Dateien, die Vorschläge für die Dynamics-Rechnung und die Beschreibung des Formats. |
st_StandardHochladen | Prüft einen eigenen Standard und speichert ihn in der Tabelle der eigenen Standards. |
st_CheckKeepWarm | Prüft und repariert das Warmhalten. Ohne Eingaben, druckt nichts. Ausgaben: Ok (Ja/Nein) und Message (Klartext). |
st_FormatLesen | Liefert die Beschreibung des Vorlagenformats in Teilen, für den KI-Assistenten. |
st_VorlageAendern | Nimmt eine Änderung an einer Vorlage entgegen, prüft sie und legt sie als KI-Änderung ab. Die gespeicherte Vorlage bleibt unverändert. |
Alle drei Druck-Aktionen können nach dem Beleg einen Flow in Power Automate starten (Eingabe FlowId). st_GenerateEInvoice hat diese Eingabe nicht.
Das PDF im Browser zeigen
In einem Button der Befehlsleiste zeigen Sie den Beleg in einem neuen Reiter. Entscheidend ist die Reihenfolge: zuerst den Reiter öffnen, dann auf den Beleg warten.
// In a button click: open the tab FIRST, then wait for the document.
// After an await, the browser silently blocks a new window.
async function showDocument(formContext) {
const tab = window.open("", "_blank");
try {
const result = await generateDocument(formContext); // from the first example
const raw = atob(result.PdfBase64);
const bytes = new Uint8Array(raw.length);
for (let i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i);
tab.location.href = URL.createObjectURL(new Blob([bytes], { type: "application/pdf" }));
} catch (error) {
if (tab) tab.close();
Xrm.Navigation.openAlertDialog({ text: "No document: " + error.message });
}
}
Fertig gebaut liefert Smart Templates das mit der Bibliothek st_button.js, samt Wartehinweis, Meldungen und mehreren Datensätzen auf einmal (siehe Aus einem Button in Dynamics).
Den Beleg per E-Mail
Der Beleg kommt als PDF-Anhang an eine E-Mail, deren Betreff und Text aus einer E-Mail-Vorlage von Dynamics stammen. Wie Sie eine E-Mail-Vorlage anlegen, beschreibt Microsoft: Vorlagen für E-Mails erstellen. Es gibt drei Wege:
| Weg | Was geschieht | Gut für |
|---|---|---|
st_CreateEmail | Ein Aufruf: Beleg erzeugen, aus der E-Mail-Vorlage einen E-Mail-Entwurf anlegen, das PDF anhängen. Gesendet wird nicht. | Der Anwender prüft die E-Mail und sendet sie selbst. |
st_SendEmail | Dasselbe, und die E-Mail geht sofort hinaus. | E-Mails ohne Prüfung. |
| Selbst gebaut | Beleg erzeugen, die E-Mail-Vorlage mit InstantiateTemplate füllen, die E-Mail anlegen, das PDF anhängen, auf Wunsch senden. | Eigene Empfänger, eigener Text, weitere Anhänge. |
Die Eingabe FlowId gibt es bei st_CreateEmail und st_SendEmail ebenso; sie startet danach einen Flow und versendet selbst nichts (siehe Einen Flow starten).
Ein Aufruf: st_CreateEmail
st_CreateEmail erzeugt den Beleg, legt aus der E-Mail-Vorlage (EmailTemplateId) einen E-Mail-Entwurf an und hängt das PDF an. Gesendet wird nichts: Der Entwurf liegt in Dynamics, der Anwender prüft ihn und sendet ihn selbst. Die Anhänge der E-Mail-Vorlage kommen als Kopie mit.
var response = service.Execute(new OrganizationRequest("st_CreateEmail") // creates a draft, nothing is sent
{
["TemplateId"] = "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42", // document template
["EmailTemplateId"] = "7a1d9c3e-5b2f-4d8a-9e6c-2b4f8d1a7c35", // email template: subject and text
["PrimaryEntity"] = "invoice",
["PrimaryId"] = context.PrimaryEntityId.ToString(),
["To"] = "contact:" + contactId // optional
});
var emailId = (string)response["EmailId"]; // the draft with the PDF attached
var message = (string)response["Message"]; // skipped recipients appear here as "WARNING:"const response = await Xrm.WebApi.online.execute({
TemplateId: "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42", // document template
EmailTemplateId: "7a1d9c3e-5b2f-4d8a-9e6c-2b4f8d1a7c35", // email template: subject and text
PrimaryEntity: "invoice",
PrimaryId: id,
To: "contact:" + contactId, // optional
getMetadata: () => ({
boundParameter: null,
operationType: 0, // 0 = action
operationName: "st_CreateEmail", // creates a draft, nothing is sent
parameterTypes: {
TemplateId: { typeName: "Edm.String", structuralProperty: 1 },
EmailTemplateId: { typeName: "Edm.String", structuralProperty: 1 },
PrimaryEntity: { typeName: "Edm.String", structuralProperty: 1 },
PrimaryId: { typeName: "Edm.String", structuralProperty: 1 },
To: { typeName: "Edm.String", structuralProperty: 1 }
}
})
});
const { EmailId, Message } = await response.json();
await Xrm.Navigation.openForm({ entityName: "email", entityId: EmailId }); // open the draft### Creates a draft with the PDF attached; nothing is sent
POST https://contoso.crm4.dynamics.com/api/data/v9.2/st_CreateEmail HTTP/1.1
Authorization: Bearer <Token>
Content-Type: application/json; charset=utf-8
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
{
"TemplateId": "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42",
"EmailTemplateId": "7a1d9c3e-5b2f-4d8a-9e6c-2b4f8d1a7c35",
"PrimaryEntity": "invoice",
"PrimaryId": "9d4e2b7a-1c3f-4e8d-b2a6-5f7c9e1d3b80",
"To": "contact:5c8e1f2a-7b3d-4a9c-8e1f-3d6b9a2c4e71"
}Ohne Code
Als Button ohne eigenen Code: Zweck »E-Mail vorbereiten und vorlegen« im Assistenten »Buttons in Dynamics verwalten«. Ein Klick legt den Entwurf mit dem Beleg im Anhang an und öffnet ihn; gesendet wird nicht. Einen Empfänger aus dem Datensatz wählen Sie im Schritt »An wen geht die E-Mail?«; der Button gibt ihn als To mit. Gibt das Feld keinen her, gilt dasselbe wie ohne diese Wahl (siehe Empfänger und Buttons: der Assistent: An wen geht die E-Mail?). Der Button ruft SmartTemplates.Button.openEmail, für alle angekreuzten Zeilen SmartTemplates.Button.openEmailAll. Die E-Mail-Vorlage wählen Sie im Assistenten fest oder je nach Bedingung (siehe Buttons: der Assistent: E-Mail-Vorlage: immer dieselbe oder je nach Bedingung). So geht es: Buttons: der Assistent: Was soll der Button tun? und Button einbauen, ändern, entfernen.
st_SendEmail hat dieselben Ein- und Ausgaben und sendet die E-Mail sofort; ohne Empfänger bricht sie ab (siehe Empfänger).
Ohne Code
Als Button ohne eigenen Code: Zweck »E-Mail sofort senden« im Assistenten »Buttons in Dynamics verwalten«. Der Button ruft SmartTemplates.Button.sendEmail, für alle angekreuzten Zeilen SmartTemplates.Button.sendEmailAll. Den Empfänger wählen Sie im Schritt »An wen geht die E-Mail?«, aus einem Verweis oder einem E-Mail-Feld des Datensatzes; der Button gibt ihn als To mit (siehe Buttons: der Assistent: An wen geht die E-Mail?). Ist das Feld an einem Datensatz leer, sendet der Button für ihn nichts und sagt es. Ohne diese Wahl geht die E-Mail an den Datensatz selbst, und ohne Empfänger bricht die Aktion ab. So geht es: Buttons: der Assistent: Was soll der Button tun? und Button einbauen, ändern, entfernen.
Selbst gebaut: E-Mail-Vorlage füllen und das PDF anhängen
Wollen Sie Empfänger, Text oder weitere Anhänge selbst bestimmen, bauen Sie die E-Mail aus den Bausteinen von Dynamics. InstantiateTemplate füllt die E-Mail-Vorlage für den Datensatz, ohne etwas anzulegen; danach legen Sie die E-Mail an und hängen das PDF als activitymimeattachment an. Die E-Mail-Vorlage muss für die Tabelle des Datensatzes gebaut sein oder vom Typ »Benutzer«.
using Microsoft.Crm.Sdk.Messages; // InstantiateTemplateRequest, SendEmailRequest
// 1. Fill the email template for this record (creates nothing yet)
var instantiated = (InstantiateTemplateResponse)service.Execute(new InstantiateTemplateRequest
{
TemplateId = new Guid("7a1d9c3e-5b2f-4d8a-9e6c-2b4f8d1a7c35"), // email template id
ObjectType = context.PrimaryEntityName, // e.g. "invoice"
ObjectId = context.PrimaryEntityId
});
// 2. Create the email with subject and text from the template
var email = instantiated.EntityCollection.Entities[0];
email["regardingobjectid"] = new EntityReference(context.PrimaryEntityName, context.PrimaryEntityId);
email["to"] = new EntityCollection(new[]
{
new Entity("activityparty") { ["partyid"] = new EntityReference("contact", contactId) }
});
var emailId = service.Create(email);
// 3. Attach the PDF from the first example
service.Create(new Entity("activitymimeattachment")
{
["objectid"] = new EntityReference("email", emailId),
["objecttypecode"] = "email",
["filename"] = "Invoice.pdf",
["mimetype"] = "application/pdf",
["body"] = pdfBase64
});
// 4. Optional: send it right away
service.Execute(new SendEmailRequest { EmailId = emailId, IssueSend = true, TrackingToken = "" });const id = formContext.data.entity.getId().replace(/[{}]/g, "");
// 1. Fill the email template for this record (creates nothing yet)
const response = await Xrm.WebApi.online.execute({
TemplateId: { guid: "7a1d9c3e-5b2f-4d8a-9e6c-2b4f8d1a7c35" }, // email template id; Edm.Guid needs { guid }
ObjectType: "invoice",
ObjectId: { guid: id },
getMetadata: () => ({
boundParameter: null,
operationType: 0, // 0 = action
operationName: "InstantiateTemplate",
parameterTypes: {
TemplateId: { typeName: "Edm.Guid", structuralProperty: 1 },
ObjectType: { typeName: "Edm.String", structuralProperty: 1 },
ObjectId: { typeName: "Edm.Guid", structuralProperty: 1 }
}
})
});
const template = (await response.json()).value[0];
// 2. Create the email with subject and text from the template
const email = await Xrm.WebApi.createRecord("email", {
subject: template.subject,
description: template.description,
"regardingobjectid_invoice_email@odata.bind": "/invoices(" + id + ")",
email_activity_parties: [
{ "partyid_contact@odata.bind": "/contacts(" + contactId + ")", participationtypemask: 2 } // 2 = To
]
});
// 3. Attach the PDF from the first example
const result = await generateDocument(formContext);
await Xrm.WebApi.createRecord("activitymimeattachment", {
"objectid_email@odata.bind": "/emails(" + email.id + ")",
objecttypecode: "email",
filename: "Invoice.pdf",
mimetype: "application/pdf",
body: result.PdfBase64
});### 1. Fill the email template for this record (creates nothing yet)
POST https://contoso.crm4.dynamics.com/api/data/v9.2/InstantiateTemplate HTTP/1.1
Authorization: Bearer <Token>
Content-Type: application/json; charset=utf-8
{
"TemplateId": "7a1d9c3e-5b2f-4d8a-9e6c-2b4f8d1a7c35",
"ObjectType": "invoice",
"ObjectId": "9d4e2b7a-1c3f-4e8d-b2a6-5f7c9e1d3b80"
}
### 2. Create the email with subject and text from step 1
POST https://contoso.crm4.dynamics.com/api/data/v9.2/emails HTTP/1.1
Authorization: Bearer <Token>
Content-Type: application/json; charset=utf-8
Prefer: return=representation
{
"subject": "<subject from step 1>",
"description": "<description from step 1>",
"regardingobjectid_invoice_email@odata.bind": "/invoices(9d4e2b7a-1c3f-4e8d-b2a6-5f7c9e1d3b80)",
"email_activity_parties": [
{ "partyid_contact@odata.bind": "/contacts(5c8e1f2a-7b3d-4a9c-8e1f-3d6b9a2c4e71)", "participationtypemask": 2 }
]
}
### 3. Attach the PDF
POST https://contoso.crm4.dynamics.com/api/data/v9.2/activitymimeattachments HTTP/1.1
Authorization: Bearer <Token>
Content-Type: application/json; charset=utf-8
{
"objectid_email@odata.bind": "/emails(<activityid from step 2>)",
"objecttypecode": "email",
"filename": "Invoice.pdf",
"mimetype": "application/pdf",
"body": "JVBERi0x…"
}Mehr dazu: Microsoft: Die Aktion InstantiateTemplate.
Eingaben
| Name | Pflicht | Bedeutung |
|---|---|---|
TemplateId | ja | Die Beleg-Vorlage. |
EmailTemplateId | ja, außer die Vorlage wählt selbst | Die E-Mail-Vorlage (template): Betreff, Text und ihre Anhänge. Ihre Anhänge kommen als Kopie in jede E-Mail. Sie muss für die Tabelle aus PrimaryEntity gebaut sein oder vom Typ »Benutzer«, sonst bricht die Aktion ab; das gilt auch für eine über wahlen gewählte. |
PrimaryEntity | ja | Die Tabelle, etwa invoice. |
PrimaryId | ja | Der Datensatz. |
To | nein | Empfänger, siehe unten. |
Cc | nein | Kopie, gleiche Schreibweise wie To. |
FlowId | nein | Cloud-Flow, der danach anlaufen soll. |
FileName | nein | Dateiname des PDF-Anhangs. Leer: der PDF-Name der Vorlage (siehe Vorlageneinstellungen: PDF-Name), ohne ihn der Name der Beleg-Vorlage. |
Trace | nein | Wird an st_GenerateDocument durchgereicht. |
In Dataverse sind alle Eingaben als freiwillig angemeldet, auch die vier Pflichtangaben. Fehlt eine, antwortet die Aktion mit einem eigenen Satz, der sagt, wozu sie gebraucht wird.
Empfänger
Mehrere Empfänger trennen Sie mit Strichpunkt oder Zeilenumbruch, nicht mit Komma. Jeder Eintrag ist eines von dreien:
a1b2c3d4-1111-2222-3333-444444444444 an id; the table is looked up
contact:a1b2c3d4-1111-2222-3333-444444444444 an id with its table (faster, unambiguous)
anna.smith@example.com an email address
- Gesucht wird in
contact,account,systemuser,queueundlead, in dieser Reihenfolge. Ein Eintrag, der nirgends gefunden wird, entfällt mit einer Warnung inMessage. - Ein Präfix gehört nur vor eine Kennung. Steht es vor einer Adresse, entfällt der Eintrag mit einer Warnung.
- Ist
Toleer und der Datensatz selbst adressierbar (eine der fünf Tabellen, in denen gesucht wird; mit ihren deutschen Namen stehen sie unter Buttons: der Assistent: Was soll der Button tun?), ist er der Empfänger. Sonst entsteht der Entwurf ohne Empfänger, undst_SendEmailbricht ab. Smart Templates rät keinen Empfänger. Ein Button gibtTomit, wenn ihm im Assistenten ein Empfänger hinterlegt ist (Parameterto:…; siehe Buttons: der Assistent: An wen geht die E-Mail?).
Die E-Mail-Vorlage aus der Vorlage wählen
Enthält die Beleg-Vorlage einen Abschnitt wahlen, wählen Wenn-Dann-Fälle die E-Mail-Vorlage, und EmailTemplateId darf fehlen. Ist EmailTemplateId gesetzt, gilt sie. Im Designer bauen Sie die Fälle im Assistenten »Buttons in Dynamics verwalten«, im Schritt zur E-Mail-Vorlage mit »Je nach Bedingung« (siehe Buttons: der Assistent: Je nach Bedingung: die Fälle).
"wahlen": {
"mailvorlage": {
"faelle": [ { "wenn": "ordertype == 'Project'", "dann": "<email template id>" } ],
"sonst": "<email template id>"
}
}
wenn ist ein Ausdruck in derselben Bedingungssprache wie die Sichtbarkeitsregeln (Vorlagenformat, Abschnitt »Bedingungen«), ausgewertet am Hauptdatensatz. Welche Felder der Assistent dafür anbietet, steht unter Bedingungen: Wo Bedingungen vorkommen.
Ausgaben
| Name | Bedeutung |
|---|---|
EmailId | Die erzeugte E-Mail. |
PdfBase64 | Der Beleg, derselbe wie im Anhang. |
FileName | Der Name des PDF-Anhangs. Leer, wenn kein PDF anhängt (E-Rechnung »nur XML« ohne Lesekopie). |
FlowRunId, TriggerRowId | Wie bei st_GenerateDocument. |
Message | Klartext. Ausgelassene Empfänger stehen hier und nur hier, als WARNING:. |
Anhänge mit E-Rechnung
Die E-Mail-Aktionen hängen an, was die Vorlage einstellt:
| Einstellung der Vorlage | Anhänge der E-Mail |
|---|---|
| keine E-Rechnung, ausgeschaltet oder »Nur wenn …« trifft nicht zu | Das PDF, wie bisher. |
| ZUGFeRD, »PDF mit eingebetteter E-Rechnung« | Ein Anhang: das PDF/A-3 mit der factur-x.xml darin. |
| »nur die E-Rechnung (XML)« | Die XML (application/xml, Name aus dem Standard, etwa XRechnung_R-2026-0042.xml, oder der PDF-Name der Vorlage mit .xml). |
| »nur die E-Rechnung (XML)« mit Lesekopie | Die XML und das PDF. |
FileName gilt weiter für das PDF; die XML behält den Namen aus dem Standard, oder sie heißt wie der PDF-Name der Vorlage mit .xml. Fehlt der E-Rechnung eine Pflichtangabe oder passt eine Rechenprobe nicht, entsteht keine E-Mail: »Der Beleg konnte nicht gebaut werden: Die E-Rechnung kann nicht erstellt werden – … — es wurde keine E-Mail erzeugt.«
Einen Flow starten
FlowId ist die Kennung eines Cloud-Flows, wie sie in Power Automate in der Adresszeile hinter /flows/ steht. Vor dem Beleg prüft die Aktion: Gibt es den Flow, ist es ein Cloud-Flow, ist er eingeschaltet, und passt er zum Datensatz? Scheitert die Prüfung, entsteht nichts. Gestartet wird ganz am Ende und asynchron; der Aufrufer wartet nicht auf den Flow.
Der Aufruf ist derselbe wie im ersten Beispiel, nur mit einer Kennung in FlowId. Versendet wird dabei nichts; der Flow tut, was Sie in ihm bauen.
var response = service.Execute(new OrganizationRequest("st_GenerateDocument")
{
["TemplateId"] = "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42",
["PrimaryEntity"] = "invoice",
["PrimaryId"] = context.PrimaryEntityId.ToString(),
["Mode"] = "pdf",
["FlowId"] = "b2e4c6a8-0d1f-4a3b-9c5e-7f8a1b2c3d4e" // Power Automate cloud flow id (address bar, after /flows/)
});
var triggerRowId = (string)response["TriggerRowId"]; // set when the flow was started through the trigger table
var flowRunId = (string)response["FlowRunId"]; // set when the flow was started directly
var message = (string)response["Message"]; // "WARNING: …" if the flow was not startedconst response = await Xrm.WebApi.online.execute({
TemplateId: "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42",
PrimaryEntity: "invoice",
PrimaryId: id,
Mode: "pdf",
FlowId: "b2e4c6a8-0d1f-4a3b-9c5e-7f8a1b2c3d4e", // Power Automate cloud flow id (address bar, after /flows/)
getMetadata: () => ({
boundParameter: null,
operationType: 0, // 0 = action
operationName: "st_GenerateDocument",
parameterTypes: {
TemplateId: { typeName: "Edm.String", structuralProperty: 1 },
PrimaryEntity: { typeName: "Edm.String", structuralProperty: 1 },
PrimaryId: { typeName: "Edm.String", structuralProperty: 1 },
Mode: { typeName: "Edm.String", structuralProperty: 1 },
FlowId: { typeName: "Edm.String", structuralProperty: 1 }
}
})
});
const { TriggerRowId, FlowRunId, Message } = await response.json();POST https://contoso.crm4.dynamics.com/api/data/v9.2/st_GenerateDocument HTTP/1.1
Authorization: Bearer <Token>
Content-Type: application/json; charset=utf-8
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
{
"TemplateId": "3f6b2c1e-8a4d-4f7b-9c2e-1d5a7b9e0c42",
"PrimaryEntity": "invoice",
"PrimaryId": "9d4e2b7a-1c3f-4e8d-b2a6-5f7c9e1d3b80",
"Mode": "pdf",
"FlowId": "b2e4c6a8-0d1f-4a3b-9c5e-7f8a1b2c3d4e"
}Ohne Code
Auch der Flow geht ohne Code: Im Assistenten »Buttons in Dynamics verwalten« wählen Sie ihn im Schritt »Soll danach ein Flow in Power Automate laufen?«; der Button gibt ihn dann als FlowId mit (siehe Buttons: der Assistent: Der Schritt »Soll danach ein Flow in Power Automate laufen?«).
- Der empfohlene Weg: ein Flow mit dem Auslöser auf der Auslösetabelle von Smart Templates. Die Aktion legt dort eine Zeile mit Flow, Vorlage, Tabelle und Datensatz an, bei den E-Mail-Aktionen auch mit der E-Mail, und der Flow läuft an. So legt ihn die Flow-Verwaltung im Designer an (Knopf »↻ Flows verwalten«, siehe Flows: Flows verwalten; was der angelegte Flow schon enthält, steht unter Flows: Das Gerüst des angelegten Flows). Wer ihn selbst baut (der lange Weg), legt in einer Lösung einen Cloud-Flow mit dem Auslöser »Wenn eine Zeile hinzugefügt, geändert oder gelöscht wird« (Microsoft Dataverse) an. Die Einstellungen dafür sind: Änderungstyp (Change type) »Erstellen«, Tabellenname (Table name) »Smart Templates Auslöser« (
st_ausloeser), Bereich (Scope) »Organisation« und unter »Zeilen filtern« (Filter rows) die Angabest_flowkennung eq '<Kennung des Flows>'. Die Kennung steht nach dem Speichern des Flows in der Adresszeile hinter »/flows/«. Dazu kommt das Einschalten. Ohne den Zeilenfilter nimmt der Flow auch die Anforderungen anderer Buttons mit. Die englischen Bezeichnungen sind an Power Automate geprüft, die deutschen Feldnamen nicht. Die Zeile trägtst_vorlageid,st_zieltabelle,st_datensatzid,st_zielsetund bei den E-Mail-Aktionenst_emailid; den Beleg holt sich der Flow damit selbst. Welches Leserecht das Konto des Flows auf diese Tabelle braucht, steht unter Rechte und Rollen: Belege drucken. - Der zweite Weg: ein Flow mit einem Dataverse-Zeilenauslöser auf der Tabelle des Datensatzes (bei den E-Mail-Aktionen auch auf
email; der Flow bekommt dann die erzeugte E-Mail). Die Aktion startet ihn direkt,FlowRunIdnennt den Systemauftrag. Er muss bedarfsgesteuert sein (ondemand), sonst weist die Prüfung ihn ab; ebenso einen Flow auf der Auslösetabelle, dessen Auslöser nicht auf neue Zeilen hört. - Beauftragt wird nur, wenn die Vorlage als
TemplateIdkam (nicht alsTemplateJson), ein Datensatz da ist und der Aufrufer ihn lesen darf. Sonst steht »WARNING: Der Flow … wurde NICHT beauftragt« inMessage; der Beleg kommt trotzdem. - Ein Flow muss in einer Lösung liegen. Ein Flow unter »Meine Flows« ist für Dataverse nicht ansprechbar.
- Bei
st_GenerateDocumentläuft der Flow nur bei einem echten PDF (Mode=pdf), geprüft wird in jedem Modus. Mit E-Rechnung gilt dasselbe:Mode=vorschauundMode=erechnungstoßen keinen Flow an, eine mitgegebeneFlowIdwird geprüft und mitWARNING:gemeldet.
Fehler und Warnungen
Bricht eine Aktion ab, entsteht kein Beleg. Ein abgewiesener Aufruf bringt einen Satz in Klartext mit, den Sie unverändert anzeigen dürfen. Im aufrufenden Plugin kommt er als FaultException<OrganizationServiceFault> an, nicht als InvalidPluginExecutionException. In JavaScript wird das Promise abgewiesen, über HTTP kommt der Status 400. Den Grund nennt die Meldung, bei st_GenerateDocument auf Englisch. Ausnahme sind die Abbrüche der E-Rechnung (auch die Ablehnung des PDF/A) und alle Abbrüche von st_GenerateEInvoice: Sie kommen in der Sprache des aufrufenden Benutzers — Deutsch bei deutscher Oberfläche, sonst Englisch; ein Anwendungsbenutzer ohne Benutzereinstellung bekommt Englisch. Warnungen in Message sind immer englisch. Kommt der Beleg mit Warnung, steht sie in Message und beginnt mit WARNING:.
using System.ServiceModel;
try
{
var response = service.Execute(request);
var message = (string)response["Message"];
if (message.Contains("WARNING:"))
{
// The document exists, but with a warning – e.g. write it to a log
}
}
catch (FaultException<OrganizationServiceFault> fault)
{
// fault.Detail.Message states the reason, e.g. a missing read privilege
throw new InvalidPluginExecutionException("No document: " + fault.Detail.Message);
}try {
const result = await generateDocument(formContext);
if (result.Message.includes("WARNING:")) {
// The document exists, but with a warning
}
} catch (error) {
Xrm.Navigation.openAlertDialog({ text: "No document: " + error.message });
}HTTP/1.1 400 Bad Request
Content-Type: application/json; odata.metadata=minimal
{
"error": {
"code": "0x80040265",
"message": "the server-side data build FAILED: 'Invoice' entity doesn't contain attribute with Name = 'Date' … No document was created: … Please check the record id, the entity name and the read privileges of the calling user."
}
}Marken in Message
| Marke | Bedeutung |
|---|---|
Client-Daten | Der Beleg entstand ohne echte Daten aus Dynamics: kein oder kein gültiger Datensatz, oder die Vorlage hat keine Datenquelle. Im Designer normal, in einer E-Mail ein leerer Beleg. |
Fremde-Tabelle | Die Hauptquelle der Vorlage steht auf einer anderen Tabelle als PrimaryEntity. |
st_GenerateDocument warnt nur; der Beleg kommt trotzdem, bei Fremde-Tabelle aber ohne Flow. Die E-Mail-Aktionen brechen bei beiden Marken ab: Lieber keine E-Mail als ein falscher Beleg beim Kunden. Ein Datensatz, zu dem die Abfrage nichts liefert, bricht jede Druck-Aktion mit einem Fehler ab.
Regeln
- Rechte: Die Aktion liest mit den Rechten des Aufrufers. Nötig ist Leserecht auf die Haupttabelle der Vorlage und auf jede Tabelle, aus der sie Daten holt (siehe Rechte und Rollen: Belege drucken). Ein eigenes Sicherheitsrecht für die Aktion gibt es nicht.
- Gespeicherte Vorlage:
TemplateIdist die Kennung einer Vorlage (st_smarttemplate); gedruckt wird ihre gespeicherte Fassung. - Eingaben als Text: Auch Kennungen sind Text. Geben Sie sie ohne geschweifte Klammern an;
formContext.data.entity.getId()liefert sie mit Klammern, deshalb dasreplaceim Beispiel. - Dauer: Ein Beleg dauert meist ein paar Sekunden, der erste nach einer längeren Pause zehn bis siebzehn Sekunden (siehe Warmhalten).
- Keine Schleifen: Rufen Sie die Aktion nicht in einer Schleife über viele Datensätze auf: Jeder Aufruf baut ein PDF, und die Sandbox gibt einem Vorgang zwei Minuten. Stapel gehören in einen asynchronen Auftrag oder einen Flow.
st_GenerateDocument: alle Ein- und Ausgaben
Eingaben
| Name | Pflicht | Bedeutung |
|---|---|---|
TemplateId | ja, oder TemplateJson | Kennung der Vorlage (st_smarttemplate). |
TemplateJson | ja, oder TemplateId | Die Vorlage als JSON, statt sie zu laden. So arbeitet der Designer. |
PrimaryEntity | nein | Logischer Name der Tabelle, etwa invoice. |
PrimaryId | nein | Kennung des Datensatzes. |
Data | nein | Beispieldaten als JSON, nur für die Vorschau. |
Mode | nein | pdf (Vorgabe), layout (Zeichenbefehle statt PDF), plan (nur der Abfrageplan, ohne die Abfragen der Vorlage auszuführen), vorschau oder erechnung (beide für den Designer, siehe E-Rechnung). |
FlowId | nein | Kennung eines Cloud-Flows in Power Automate, der nach dem Beleg anlaufen soll. Siehe Flow starten. |
Trace | nein | Schaltet das Abfrageprotokoll ein. |
Fehlt der Datensatz, entsteht der Beleg aus den mitgeschickten Beispieldaten. Message trägt dann die Marke Client-Daten (siehe Marken).
Ausgaben
| Name | Bedeutung |
|---|---|
PdfBase64 | Der Beleg als Base64. Leer bei layout und plan, bei erechnung und bei einer E-Rechnung »nur XML« ohne Lesekopie. |
XmlBase64 | Die E-Rechnung als eigene XML-Datei (Base64): bei »nur XML« (pdf, vorschau) und bei erechnung, wenn die XML gültig ist. Sonst leer, auch bei »PDF mit eingebetteter E-Rechnung«: Dort steckt die XML im PDF. Wer die Ausgabe auswertet: XmlBase64 gefüllt heißt eine XML-Datei liefern, PdfBase64 gefüllt ein PDF. |
FileName | Der Name des PDF in PdfBase64: der PDF-Name der Vorlage (siehe Vorlageneinstellungen: PDF-Name), ohne ihn der Name der Vorlage mit - statt der Zeichen, die in Dateinamen nicht gehen, und .pdf; derselbe Name, den die E-Mail-Aktionen dem Anhang geben. Leer, wenn PdfBase64 leer ist. |
XmlFileName | Der Dateiname der E-Rechnung aus dem Standard, etwa XRechnung_R-2026-0042.xml, oder der PDF-Name der Vorlage mit .xml. Leer, wenn XmlBase64 leer ist. |
LayoutJson | Bei layout die Zeichenbefehle als JSON. Bei plan der Abfrageplan als lesbarer Text in FetchXML-Schreibweise, eine <fetch> je Abfrage (kein einzelnes XML-Dokument). |
ChoicesJson | Das Ergebnis der Wenn-Dann-Wahlen der Vorlage (Abschnitt wahlen), etwa die gewählte E-Mail-Vorlage. Leer ohne wahlen und bei plan. |
FlowRunId | Der Systemauftrag eines direkt angestoßenen Flows. Sonst leer. |
TriggerRowId | Die Zeile in der Auslösetabelle, wenn ein Flow über sie beauftragt wurde. Sonst leer. |
Message | Erfolgszeile, Kennzahlen und Warnungen. Warnungen beginnen mit WARNING:. |
Alle Ausgänge sind immer vorhanden. »Nicht zutreffend« heißt eine leere Zeichenkette.
Aus Buttons und Power Automate
Aus einem Button in Dynamics
Für Buttons in der Befehlsleiste von Dynamics liefert Smart Templates die Bibliothek st_button.js mit. Ihre Funktionen rufen die Aktionen dieser Seite auf. Welche Funktion welche Aktion ruft, steht in der Spalte ruft Aktion unter Was beim Klick geschieht: Die acht Einträge für das Feld »Funktion«. Die Funktionen downloadEInvoice und downloadEInvoiceAll rufen st_GenerateEInvoice (siehe E-Rechnung).
Welche Funktion welchem Zweck dient und welche Parameter in welcher Reihenfolge folgen, steht an derselben Stelle; wie der Weg geschrieben wird, unter Buttons: der Assistent: Der Weg ist fertig: Probe und Wegtext; was Anwender beim Klick sehen und wann ein Button abbricht, unter Was beim Klick geschieht. Der Assistent »Buttons in Dynamics verwalten« im Designer stellt alle Werte zum Kopieren bereit.
Aus Power Automate
Die Aktionen sind ungebunden und sichtbar. In einem Flow rufen Sie sie über den Konnektor Microsoft Dataverse mit der Aktion »Perform an unbound action« auf, zum Beispiel st_GenerateDocument mit TemplateId, PrimaryEntity, PrimaryId und Mode = pdf. Die Felder heißen dort »Item/TemplateId«, »Item/PrimaryEntity«, »Item/PrimaryId« und »Item/Mode«; im Flow, den der Designer anlegt, trägt der Schritt den Namen »Beleg erzeugen«. Mit PdfBase64 legen Sie dann eine Datei an, senden eine E-Mail oder starten eine Genehmigung. Hat die Vorlage eine E-Rechnung »nur XML«, steht die XML in XmlBase64 und ihr Name in XmlFileName; PdfBase64 ist dann die Lesekopie oder leer.
st_GenerateDocument mit ihren vier Feldern. Das rote Band steht hier, weil dem Beispiel-Flow noch keine Verbindung zugewiesen ist.
- 1Der Kopf der Karte mit dem Dataverse-Symbol. Der Designer nennt den Schritt »Beleg erzeugen«.
- 2»Action Name«: der Name der Aktion, hier
st_GenerateDocument. - 3Die drei Kennungen: Vorlage, Tabelle und Datensatz. Im angelegten Flow kommen sie als Datenwerte aus der Auslösezeile.
- 4»Item/Mode« mit dem Wert
pdf: Der Beleg kommt als fertiges PDF, als Base64-Text inPdfBase64.
E-Rechnung
Eine Vorlage erzeugt eine E-Rechnung, wenn ihr Schlüssel eRechnung "aktiv": true trägt. Was der Anwender einstellt und liest, steht unter E-Rechnung: ZUGFeRD und XRechnung. Zuordnung, Prüfung, XML und PDF/A macht Smart Templates an einer einzigen Stelle; Plugin und lokaler Dienst rufen dieselbe. Vorlagen ohne eingeschaltete E-Rechnung laufen wie bisher.
Die Vorgabe ist streng: Fehlt eine Pflichtangabe, passt eine Rechenprobe nicht, ist ein Einzelpreis negativ oder lehnt der Druck das PDF/A ab, dann entsteht nichts, auch kein normales PDF und keine Lesekopie. Der Fehlertext ist der Satz aus dem Kern. Einzige Ausnahme ist Mode=vorschau. Beträge werden vor der Prüfung kaufmännisch auf zwei Nachkommastellen gerundet; Preise, Mengen und Prozentsätze nicht.
Die Modi von st_GenerateDocument mit E-Rechnung
| Mode | »PDF mit eingebetteter E-Rechnung« (ZUGFeRD) | »nur XML« | Fehler der E-Rechnung | »Nur wenn …« trifft nicht zu |
|---|---|---|---|---|
pdf (Vorgabe; Button, E-Mail, Flow, eigener Code) | PdfBase64 ist das PDF/A-3 mit der XML. | XmlBase64 und XmlFileName; PdfBase64 ist die Lesekopie oder leer. | Abbruch mit dem Satz aus dem Kern. | Der Beleg wie bisher, eine Notiz in Message. |
vorschau (nur die Voll-Vorschau des Designers) | PDF/A-3 mit der XML. | Das normale PDF; dazu XmlBase64. | Das PDF ohne XML, dazu WARNING: e-invoice: …. | Wie pdf. |
erechnung (»Mit Beispieldatensatz prüfen« im Designer, st_GenerateEInvoice) | Kein PDF; der Bericht steht in LayoutJson, XmlBase64 bei gültiger XML. | Ebenso. | Der Bericht mit den Befunden. | Der Bericht mit angewendet: false. |
Mode=vorschauundMode=erechnungstoßen keinen Flow an.Mode=layoutundMode=planlaufen ohne E-Rechnung; der Plan sammelt ihre Felder trotzdem ein.- In
Messagesteht bei eingeschalteter E-Rechnung hinter der Kopfzeile ein Abschnitt » · E-invoice: …« (englisch, wie der Rest der Zeile). Er nennt, was geliefert wurde: »embedded (PDF/A-3b, factur-x.xml, n bytes)«, »XML only (Datei, n bytes, with reading copy)«, »not applied (condition not met)« oder »not created - the PDF has no e-invoice«. Bei »nur XML« ohne Lesekopie heißt die KopfzeileOK: e-invoice XML, n bytes, weil es keine Seiten gibt. - Alle Zweige setzen
XmlBase64undXmlFileName, leer, wo es keine E-Rechnung gibt.
st_GenerateEInvoice: nur die XML
| Eingabe | Bedeutung |
|---|---|
TemplateId | Die Vorlage (st_smarttemplate) mit eingeschalteter E-Rechnung. |
PrimaryEntity | Die Tabelle, etwa invoice. |
PrimaryId | Der Datensatz. |
| Ausgabe | Bedeutung |
|---|---|
XmlBase64 | Die E-Rechnung als XML (Base64); bei ZUGFeRD die factur-x.xml, die sonst im PDF steckt. |
FileName | Der Name aus dem Standard, etwa XRechnung_R-2026-0042.xml, oder der PDF-Name der Vorlage mit .xml. |
Message | OK: e-invoice <Name> (<Dokument>), n bytes, <Datei>, dahinter die Hinweise der E-Rechnung (WARNING:). |
Die Aktion ruft st_GenerateDocument mit Mode=erechnung, in den Rechten des Aufrufers; Datenaufbau und Erzeuger gibt es nur einmal. Sie bricht ab, wenn der Datensatz fehlt, der Beleg nicht aus dem echten Datensatz entstünde, die Vorlage keine eingeschaltete E-Rechnung hat, ihr »Nur wenn …« nicht zutrifft oder die E-Rechnung einen Fehler hat. Die Sätze stehen unter Probleme und Meldungen: E-Rechnung. Die Vorprüfung für PDF/A zählt hier nicht, weil kein PDF entsteht.
st_StandardLesen und st_StandardHochladen: die Standards
| Eingabe von st_StandardLesen | Bedeutung |
|---|---|
Kennung | Etwa xrechnung-ubl. Leer liefert die Liste aller Standards, mitgelieferte und eigene. |
Fassung | Etwa 3.0.2. Leer ist die neueste gültige. |
Teil | Leer oder uebersicht, pflicht, abschnitt:<id>, codeliste:<id> (JSON); anmerkung (die Erklärungsdatei), schema:<datei> (eine Datei des Schemasatzes), formatschema (Text); vorschlaege (die Vorschläge aus den Standardfeldern der Dynamics-Rechnung, JSON; mit Kennung auf den Standard zugeschnitten); format (die Beschreibung aus Eigene Standards für die E-Rechnung als Markdown, im Ausgang Text); liste. format, formatschema und vorschlaege gehen ohne Kennung. |
Sprache | de oder en für die Texte der Übersicht. |
| Ausgaben | Json bei Liste und Übersicht, Text bei Dateien (der jeweils andere ist leer), Message. Ein unbekannter Standard oder Teil ist ein Fehler mit einem deutschen Satz. |
| Eingabe von st_StandardHochladen | Bedeutung |
|---|---|
Inhalt | Eine Erklärungsdatei (XSD) als Text, oder |
PaketBase64 | ein ZIP mit der Erklärungsdatei, bei eigenem Schemasatz mit diesem, als Base64, höchstens 768 KiB gepackt. |
Ersetzen | ja ersetzt eine vorhandene gleiche Fassung. Leer oder nein: nicht. Ein anderer Wert ist ein Fehler. |
Ausgabe Ergebnis | JSON mit ok, kennung, fassung, befunde, id und ersetzt. Bei Ablehnung ok: false mit den Befunden; das ist keine Ausnahme, die Befundliste mit ihren Fundstellen ist die Antwort. |
- Geprüft wird, bevor etwas gespeichert wird; die Kennungen der mitgelieferten Standards sind gesperrt. Gespeichert wird in den Rechten des Aufrufers: Anlegen und Schreiben auf die Tabelle der eigenen Standards hat die Rolle »Smart Templates Designer« (siehe Rechte und Rollen: Vorlagen gestalten).
- Lesen läuft mit dem Dienst des Systems: Wer drucken darf, braucht kein Recht auf diese Tabelle.
- Löschen kann nur die Web-API, und nur auf eigene Standards (Tabelle
st_erechnungstandard, Rolle »Smart Templates Designer«). Mitgelieferte lassen sich nicht löschen.
Der Button
Die Funktionen SmartTemplates.Button.downloadEInvoice und …downloadEInvoiceAll rufen st_GenerateEInvoice und bieten die XML zum Speichern an, bei mehreren Zeilen in einer ZIP-Datei. Sie kennen keinen Flow (siehe Was beim Klick geschieht: Die E-Rechnung).
Aktionen des KI-Assistenten
st_FormatLesen
Eingabe Teil: Grundlagen, Daten, Ausdrücke, Objekte, Tabellen, Beispiel oder alle; leer liefert die Liste der Teile. Ausgabe Text: der Teil der Formatbeschreibung als Markdown, dieselbe Beschreibung wie im Kapitel Vorlagenformat.
st_VorlageAendern
| Name | Bedeutung |
|---|---|
VorlageId | Kennung der Vorlage (st_smarttemplateid). |
Aenderungen | Die Änderung als JSON Patch (RFC 6902) auf das JSON der gespeicherten Vorlage. Alles oder nichts: Scheitert ein Schritt, gilt keiner. |
Beschreibung | Pflicht: ein Satz, was geändert wird und warum. Der Designer zeigt ihn an. Fehlt er, antwortet die Aktion mit ok: false und einem Fehler, dessen wo Beschreibung lautet. |
Ergebnis (Ausgabe) | JSON mit ok, fehler und hinweise (je wo und was), angewendet, vorlage, aenderungId und text. |
Die Aktion liest die Vorlage mit den Rechten des Aufrufers, wendet die Änderung an, prüft das Ergebnis wie beim Import und legt es in »Smart Templates KI-Änderung« ab. Die gespeicherte Vorlage ändert sie nicht. Ein Fehler kommt als Antwort mit ok: false, nicht als Ausnahme. Der Designer übernimmt die abgelegte Änderung in die offene Vorlage (siehe Mit dem KI-Assistenten in Copilot arbeiten: Was dann passiert).