← Blog
Business Apps·09. Juli 2026·11 min Lesezeit

Dataverse Custom API Toolkit: Custom-API-Endpunkte direkt in VS Code bauen

Custom-API-Metadaten im Maker Portal von Hand pflegen ist fehleranfällig — ein Tippfehler im uniqueName, eine vergessene Response-Property, und der Aufruf kracht erst zur Laufzeit. Das Dataverse Custom API Toolkit ist eine VS-Code-Extension über der dataverse-custom-api-CLI: Custom-API-Endpunkte im Tree durchsuchen, Parameter im Formular bearbeiten, gegen Dataverse diffen und mit Dry-Run synchronisieren — versioniert als JSON im Workspace.

Dataverse Custom API Toolkit: Custom-API-Endpunkte direkt in VS Code bauen

Wenn du in Dataverse schon mal eine Custom API von Hand angelegt hast, kennst du das Gefummel: Im Maker Portal klickst du dich durch Message, Request-Parameter und Response-Properties, tippst uniqueName, bindingType und Typen einzeln ein — und merkst erst beim ersten Aufruf, dass ein Parameter fehlt, ein Name einen Buchstabendreher hat oder eine Response-Property nie angelegt wurde. Kein Diff, keine Versionierung, kein „vorher mal trocken durchspielen”.

Das Dataverse Custom API Toolkit ist eine VS-Code-Extension, die genau diese Arbeit in den Editor holt. Sie ist ein grafischer Aufsatz auf die CLI dataverse-custom-api (dvc): Du siehst deine Custom-API-Endpunkte in einem Tree, bearbeitest ihre Parameter in einem Formular, exportierst sie als versionierbare JSON-Datei in deinen Workspace und spielst Änderungen erst als Simulation, dann live gegen Dataverse. Kernregel wie beim manuellen Weg vermieden: du siehst vor jedem Schreibvorgang genau, was passieren würde.

Grundbegriffe: Custom API, Request-Parameter, Response-Property

Kurz eingeordnet, falls du nicht täglich damit arbeitest:

  • Eine Custom API ist eine benutzerdefinierte Nachricht (Action oder Function) in Dataverse — also ein eigener Endpunkt, den du wie WhoAmI oder Create aufrufen kannst, nur mit deiner eigenen Logik dahinter. Definiert wird sie über Metadaten: Name, Binding, ein optionaler Plugin-Typ, plus ihre Parameter.
  • Ein Request-Parameter ist ein Eingabewert der API — mit uniqueName, Typ (String, Integer, Entity …) und dem Flag, ob er optional ist.
  • Eine Response-Property ist ein Rückgabewert — Name und Typ, den der Aufrufer zurückbekommt.

Statt dieses Geflecht im Portal zu klicken, beschreibst du es als JSON und lässt das Toolkit den Abgleich mit Dataverse machen.

Screen für Screen: die Oberfläche

Nach der Installation bekommst du in der Activity Bar ein eigenes Icon des Dataverse Custom API Toolkit. Dahinter sitzen drei Panels: Environments, Custom API und Actions.

Die Activity-Bar-Ansicht des Dataverse Custom API Toolkit in VS Code: unter Environments die verbundene Umgebung „dev1" (grüner Haken), darunter die geladenen Custom-API-Endpunkte und der Actions-Bereich mit Connect Environment, New Custom API, Save & Sync to Dataverse und Validate App-User Privileges.

1. Environments — deine Umgebungen

Die Environments-View listet deine gespeicherten Dataverse-Umgebungen. Umgebungen werden global in der Extension verwaltet (nicht pro Workspace), Secrets liegen sicher in VS Codes context.secrets — nie im Klartext im Projekt.

In der Titelleiste der View sitzen Connect Environment (+) und Refresh. Pro Eintrag hast du inline Use (verbinden/aktiv setzen), Edit und Remove.

Connect Environment öffnet einen geführten Assistenten — eine Kette von Eingabefeldern oben im VS-Code-Fenster:

  1. Display Name — ein sprechender Name.
  2. Dataverse Environment URL — z. B. https://org.crm4.dynamics.com (wird auf http… geprüft).
  3. Authentication Mode — Auswahl aus deviceCode (Device Code Flow, empfohlen), interactiveBrowser (Browser-Login) oder clientSecret (App-only).
  4. Tenant ID und Client ID deiner Azure-AD-App-Registrierung.
  5. Client Secret — nur bei clientSecret, als verdecktes Passwortfeld; landet in den VS-Code-Secrets.

Zum Schluss schreibt die Extension eine kompatible auth.json in ihren Runtime-Cache (die Brücke zur CLI) und ruft connect auf.

Der „Authentication Mode"-QuickPick des Connect-Wizards mit den drei Optionen deviceCode (Device Code Flow), interactiveBrowser (Interactive Browser Login) und clientSecret (Client Secret Flow).

2. Custom-API-Ansicht — dein Arbeitsbereich

Das Herzstück. Die Custom-API-View listet jede Custom API der aktiven Umgebung. Jeder Eintrag zeigt neben dem uniqueName einen Status als Kurztext: local · dirty · active — und ein passendes Icon:

  • grüner Haken — aktive API, lokal und in sync,
  • ⚠ Warnung — lokale Datei weicht von der zuletzt gespeicherten ab (dirty),
  • Code-Datei-Icon — lokal exportiert, sauber.

Oben rechts zeigt ein Badge die Anzahl (z. B. „7 von 20”, wenn ein Filter aktiv ist). In der Titelleiste sitzen Refresh, Filter und Search by Name; der Titel spiegelt aktive Filter als Chips wider — etwa Custom API · no private · Global, Entity · "reorder".

Pro Eintrag hast du inline: Use (als aktive API setzen), Export (aus Dataverse in eine lokale JSON ziehen) und — sobald eine lokale Datei existiert — Open JSON, Edit und Save & Sync. Im Kontextmenü zusätzlich Diff vs Remote und Remove Local.

Die Custom-API-View mit Einträgen in verschiedenen Zuständen: „ccsm_AnotherOneAgain" ist dirty (gelbes Warndreieck), „ccsm_ProvisionCustomer" ist active (grüner Haken); rechts der geöffnete Editor mit den Response Properties.

3. Der Custom-API-Editor — das eigentliche Bearbeiten

Klickst du bei einer lokalen API auf Edit, öffnet sich ein Formular-Editor (Webview) als eigener Tab „Edit <uniqueName>”. Der Titel bekommt einen ● Punkt, sobald du etwas Ungespeichertes hast, und ganz oben erscheint ein Dirty-Banner („Unsaved changes — Save to write locally, or Reset to discard.”).

Der Editor hat drei Abschnitte:

General — die Kopfdaten der API in einem Raster: Unique Name (mit immutable-Badge und der Warnung, dass eine Änderung die ganze API löschen und neu anlegen würde), Display Name, Name, Binding Type (Global / Entity / EntityCollection), Description, Execute Privilege Name, Bound Entity Logical Name, die Plugin-Felder (Plugin Type Name, Plugin Type ID schreibgeschützt, Plugin Assembly Name …) und Allowed Custom Processing Step Type (None / AsyncOnly / SyncAndAsync). Dazu drei Checkboxen: Is Function, Is Private, Workflow SDK Step Enabled.

Request Parameters — eine Tabelle (Unique Name · Display Name · Description · Type · Optional · Actions) mit Add Parameter. Jede Zeile lässt sich aufklappen, um Details wie Logical Entity Name zu setzen.

Response Properties — dieselbe Idee ohne die Optional-Spalte, mit Add Property.

Für Type hast du überall dieselbe feste Auswahl: Boolean, DateTime, Decimal, Entity, EntityCollection, EntityReference, Float, Integer, Money, Picklist, String, StringArray, Guid.

Unten die Werkzeugleiste: Save, Save & Sync to Dataverse, Reset, Preview Payload, Open Saved JSON und — falls die CLI es unterstützt — Diff with Remote.

Der Custom-API-Editor (Dark Theme): General-Raster mit immutable-Badges, ein aufgeklappter Request-Parameter mit Typ-Dropdown und die Footer-Toolbar. Oben das gelbe Dirty-Banner. Der Custom-API-Editor mit aufgeklapptem Request-Parameter ccsm_TargetItemType, Logical Entity Name und Unique Name tragen das immutable-Badge. Oben zeigt das gelbe Dirty-Banner ungespeicherte Änderungen; das geänderte Feld bekommt einen gelben Rand.

Derselbe Editor im Light Theme, komplett mit Request Parameters, Response Properties und der Footer-Toolbar. Die helle Variante — unten die vollständige Werkzeugleiste: Save, Save & Sync to Dataverse, Reset, Preview Payload, Open Saved JSON, Diff with Remote.

4. Der Sync-Plan — erst schauen, dann schreiben

Save schreibt nur die lokale JSON. Save & Sync to Dataverse öffnet daneben den Sync-Plan (Webview „Sync: <uniqueName>”). Zuerst läuft eine Fortschritts-Notification („Checking sync status…”): Das Toolkit diffed deine lokale Definition gegen Dataverse. Ist alles gleich, meldet es schlicht „already in sync — no changes needed” und macht nichts.

Gibt es Unterschiede, siehst du eine Operationsliste — jede geplante Änderung als eigene Zeile. Wenn destruktive Schritte nötig sind (weil ein immutables Feld geändert wurde), erklärt ein Abschnitt „⚠ Why are destructive operations needed?” im Klartext, welches Feld sich geändert hat und warum daraus ein Löschen-und-Neu-Anlegen folgt.

Zwei Buttons: Simulate (Dry Run — spielt jede Operation durch, ohne zu schreiben) und Execute (live). Jede Operation bekommt live einen Status: running → ok / failed samt Dauer; bei einem Fehler stoppt der Lauf.

Der Sync-Plan (Dark Theme): drei Operationen (update/create/recreate) mit farbigen Aktions-Badges, der „Why are destructive operations needed?"-Kasten und die Buttons Simulate/Execute. Der Sync-Plan vor dem Schreiben: ein recreate ist nötig, weil sich der Typ von ccsm_NewPosition geändert hat — der gelbe Kasten erklärt genau warum. Nichts wird geschrieben, bis du auf Execute klickst.

Derselbe Sync-Plan im Light Theme. Dieselbe Ansicht hell — die Aktions-Badges (update, create, recreate) und der ⚠ destructive-Marker bleiben in beiden Themes farblich eindeutig.

5. Actions & Diff

Die Actions-View ist dein Statusboard: Sie zeigt oben die aktive Umgebung (mit URL) und die aktive Custom API, darunter Schnellzugriffe: Connect Environment, Refresh, Export Current API, Diff Current API, Save & Sync to Dataverse.

Diff öffnet den Metadaten-Vergleich lokal ↔ Dataverse als JSON-Dokument daneben — praktisch, um vor dem Sync genau zu sehen, was abweicht.

Die Diff-Ansicht (Diff Current API): rechts das JSON-Ergebnis mit isDifferent: false und einer summary der Request-/Response-Änderungen (none/create/update/delete/recreate), links der Editor — so siehst du vor dem Sync genau, was abweicht.

Der Workflow in einem Satz

Umgebung verbinden → Custom API auswählen → Export (Dataverse → lokale JSON) → im Formular editieren → Preview Payload / Diff prüfen → Simulate (Dry Run) → Execute (live).

Weil die exportierte JSON in deinem Workspace liegt, kannst du sie ganz normal versionieren (Git), im Team reviewen und über den Diff jederzeit gegen die Umgebung abgleichen. Änderst du die Datei direkt im Text-Editor oder per CLI, merkt die Extension das über einen File-Watcher und aktualisiert den Tree.

Validierung & Diagnostics

Das Toolkit fängt Fehler an mehreren Stellen ab, bevor sie in Dataverse einschlagen.

Direkt im Editor markiert es immutable Felder mit einem Badge und warnt, wenn du eines änderst — denn Dataverse lässt manche Felder nicht nachträglich ändern, sondern nur per delete + recreate. Änderst du z. B. den Typ eines Request-Parameters, plant das Toolkit automatisch ein Ersetzen statt eines Updates und sagt dir das im Sync-Plan.

Als eigene Aktion gibt es zusätzlich Check Metadata Consistency: Ein Klick prüft, ob deine lokale Definition noch deckungsgleich mit Dataverse ist. Ist alles sauber, siehst du „No metadata mismatches found” — inklusive der vollständigen Request-Parameter- und Response-Property-Listen.

Das Ergebnis von „Check Metadata Consistency" (Metadata Check): grünes „No metadata mismatches found", „Local definition is in sync with Dataverse", darunter Binding Type und Processing Steps sowie die Request-Parameter- und Response-Property-Listen.

Die tiefere Regelprüfung liefert die CLI (dvc api validate) — rein lokal, blockiert nichts, gibt dir sofort Feedback. Diese Regeln solltest du im Kopf haben:

RegelBedeutung
uniqueName mit Publisher-Präfix (z. B. ccsm_), max. 128 ZeichenOhne Präfix / zu lang → Fehler
name / displayName max. 100 ZeichenÜberschreitung → Fehler
description max. 300 ZeichenÜberschreitung → Fehler
bindingType ∈ Global / Entity / EntityCollectionAnderer Wert → Fehler
boundEntityLogicalName bei Entity / EntityCollectionPflicht, sonst Fehler
logicalEntityName nur bei Typ Entity / EntityReferenceSonst überflüssig / Info
Function braucht ≥ 1 Response-PropertySonst Fehler

Die Severity-Stufen der CLI:

SeverityHeißt
errorBlockierend — Dataverse würde die Anlage mit einem 400 ablehnen.
warningWird akzeptiert, weicht aber von der Empfehlung ab.
infoHinweis, z. B. ein offener Entity-Typ ohne logicalEntityName.

Jeder Befund kommt als strukturierter JSON-Envelope (CcdvCommandResult) mit code, jsonPath und suggestedFix — genau das Format, das sich später sauber ins VS-Code-Problems-Panel bzw. als Quick Fix einklinken lässt.

Berechtigungen: der häufige Stolperstein

Damit ein Sync durchläuft, braucht der verbundene Benutzer die passenden Rechte. Die CLI prüft das mit dvc api validate-privileges: prvRead/Create/Write/Delete auf CustomAPI, dazu prvAppendToPluginType und prvCreateSdkMessageProcessingStep.

Dieselbe Prüfung gibt es als Ein-Klick-Aktion in der Extension — Validate App-User Privileges in der Actions-Leiste. Das Ergebnis erscheint im Output-Kanal „DVC”: jedes der sechs Rechte mit grünem Haken und die Klartext-Zusammenfassung „All 6 privileges available”.

Das Ergebnis von „Validate App-User Privileges" im Output-Panel „DVC": alle sechs benötigten Rechte — Read/Create/Update/Delete Custom API, PluginType Binding und Create Plugin Steps — sind mit grünem Haken verfügbar, gefolgt von „All 6 privileges available".

Wichtig ist der Graceful Fallback: Fehlt prvAppendToPluginType, bricht der Lauf nicht hart ab — das Toolkit legt die Custom API stattdessen ohne Plugin-Typ-Bindung an und gibt eine Warning aus. Du bekommst also ein nutzbares Ergebnis plus den klaren Hinweis, welches Recht fehlt. Im Extension-UI äußert sich ein echtes Rechteproblem als fehlgeschlagene Operation im Sync-Plan (Status failed mit Meldung).

Unter der Haube

Die Extension baut die Dataverse-Aufrufe nicht selbst — sie ist ein Wrapper um das npm-Paket ccdvcustomapi (dieselbe Engine wie die dvc-CLI). Über eine kompatible auth.json im Runtime-Cache reicht sie deine Umgebungs- und Auth-Daten an die CLI-Engine weiter; Secrets bleiben derweil in den VS-Code-Secrets. Custom-API-Definitionen liegen als JSON-Katalog im Workspace, jede Änderung geht über denselben Envelope (CcdvCommandResult) wie in der CLI.

Zwei Details, die den Alltag angenehm machen:

  • Dirty-Erkennung per Hash. Beim Export merkt sich das Toolkit einen Hash der Datei. Änderst du sie später, vergleicht es neu und markiert die API im Tree als dirty — du siehst also auf einen Blick, was noch nicht synchronisiert ist.
  • File-Watcher. Legst du eine Custom-API-JSON per CLI an oder editierst sie im Text-Editor, aktualisiert sich der Tree automatisch. Extension und CLI teilen sich denselben Workspace-Ordner, ohne sich in die Quere zu kommen.

Installieren & loslegen

Voraussetzung ist die CLI dataverse-custom-api (@brunsforge/dataverse-custom-api) — die Extension ist der grafische Aufsatz darauf. Den Quellcode und die Dokumentation der CLI findest du offen auf GitHub: github.com/brunsforge/dataverse-custom-api.

Die Extension liegt im Visual Studio Marketplace als Dataverse Custom API Toolkit (Publisher brunsforge). Installieren direkt in VS Code über Extensions → „Dataverse Custom API Toolkit” oder per Kommandozeile:

code --install-extension brunsforge.dataverse-custom-api-toolkit

Der Kurz-Workflow, wenn alles installiert ist: In der Activity-Bar-Ansicht des Toolkits über Connect Environment deine Dataverse-Umgebung verbinden (Device Code reicht), in der Custom-API-Ansicht die gewünschte API mit Export lokal ziehen, mit Edit im Formular anpassen, mit Preview Payload oder Diff prüfen, was sich ändern würde, dann Save & Sync öffnen und den Plan erst Simulate, dann Execute. Ab da lebt deine Custom-API-Definition als versionierte JSON in deinem Repo — reviewbar, diffbar, wiederholbar.

Siehe auch