Zum Hauptinhalt springen
Version: 4.1 (2026 H2)

Admin API


Die Admin API stellt Schnittstellen zum Benutzer-, Profil-, Gruppen-, Organisations- und Berechtigungs-Management zur Verfügung. Zusätzlich lassen sich Vorlagen und Snippets (Textbausteine) abfragen und verwalten. Die Endpunkte sind als versionierte REST-API unter /api/v3/{datasourceId}/Admin/... ausgelegt.

Authentifizierung​

Um die Admin APIs aufzurufen, muss in der primedocs.config ein entsprechender Client registriert sein, siehe hierfür primedocs.config.

Nach der Registrierung kann damit ein AccessToken vom IdS angefordert werden.

Dieses PowerShell-Beispiel zeigt den Bezug des AccessTokens:

# Configuration
$datasourceId = "b78c3707-d7c7-4fc7-b97f-87d70f63c1ac"
$tokenUrl = "https://{instanz}/ids/connect/token"
$clientID = "CustomApiClient"
$clientSecret = "CustomClient_Secret_123"
$scope = "pd_AdminWebApi"

$tokenRequestHeaders = @{
"Content-Type" = "application/x-www-form-urlencoded"
}

$tokenRequestBody = @{
client_id = $clientID
client_secret = $clientSecret
grant_type = "client_credentials"
scope = $scope
}

# Request the access token

try {
$tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method POST -Headers $tokenRequestHeaders -Body $tokenRequestBody
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}

if (-not $tokenResponse.access_token) {
Write-Error "Failed to obtain an access token!"
exit 1
}

# Access token information
Write-Host "Access Token: $($tokenResponse.access_token)"
$accessToken = $tokenResponse.access_token

Query-Syntax​

Die Admin API bietet typische "CRUD" (Create / Read / Update / Delete) Endpunkte als HTTP API an.

Um Daten gezielt zu suchen, bieten folgende GET-Endpunkte einen "query" Parameter an:

HTTP GET-EndpunktBeschreibung
/api/v3/{datasourceId}/Admin/AppUserGroupsGibt eine Liste von "AppUserGroups" zurück.
/api/v3/{datasourceId}/Admin/GroupsGibt eine Liste von "UserGroups" zurück.
/api/v3/{datasourceId}/Admin/UsersGibt eine Liste von "Users" zurück.
/api/v3/{datasourceId}/Admin/TemplatesGibt eine Liste von "Templates" zurück.
/api/v3/{datasourceId}/Admin/OrganizationUnitsGibt eine Liste von "OrganizationUnits" zurück.

Alle diese APIs geben eine paginierte Liste der Daten zurück. Über den "Query"-Parameter kann eine Filterung/Suche ausgelöst werden.

Die Syntax setzt sich aus [Eigenschaft]:"[Filter]" [WeitereEigenschaft]:"[Weiterer Filter]"... zusammen.

" können optional um den Filter gesetzt werden - insbesondere wenn Leerzeichen Teil des Filterkriteriums sind.
Einige Eigenschaften unterstützen den *-Wildcard Operator am Anfang und Ende.
Die einzelnen Filter sind UND-verknüpft.

Beispiel:

https://{instanz}/webapi/api/v3/{datasourceId}/Admin/Templates?query=localizedName:*brief%20active:true

Sucht alle aktiven Vorlagen, deren Namen mit "brief" enden.

AppUserGroups​

Mögliche "Query"-Optionen:

  • title: Suche nach Titel
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • primarySid: Suche nach der PrimarySid
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.

Beispiel:

title:Admin primarySid:123* = Sucht alle AppUserGroups welche den Titel "Admin" tragen und mit der primarySid 123 beginnen.

UserGroups​

Mögliche "Query"-Optionen:

  • title: Suche nach Titel
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • primarySid: Suche nach der PrimarySid
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.

Beispiel:

title:Admin primarySid:123* = Sucht alle UserGroups welche den Titel "Admin" tragen und mit der primarySid 123 beginnen.

Users​

Mögliche "Query"-Optionen:

  • title: Suche nach Titel
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • primarySid: Suche nach der PrimarySid
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • field[<User.FieldId>]: Suche nach einem konfigurierbaren Benutzerfeld (z.B. field[User.FirstName])
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.

Beispiel:

title:"John*" Field[User.EmailField]:"*foobar.com" = Sucht alle Users welche im Titel am Anfang "John" stehen haben und im Benutzerfeld User.EmailField die E-Mail-Adresse mit foobar.com endet.

Templates​

Mögliche "Query"-Optionen:

  • templateId: Suche nach der TemplateId
    • Muss eine GUID sein.
  • metaTemplateId: Suche nach der MetaTemplateId
    • Muss eine GUID sein.
  • active: Suche nach aktiven/inaktiven (gelöschten) Vorlagen
    • Muss ein Bool (True, False) sein.
  • templatestate: Suche nach dem Vorlagen Status
    • Unterstützt: 0 (= InProgress), 1 (= InTest), 2 (= Released)
  • templateGroupId: Suche nach der übergeordneten Vorlagen Gruppe
    • Muss eine GUID sein.
  • localizedName: Suche nach dem Namen.
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • localizedDescription: Suche nach der Beschreibung.
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • tags: Suche nach Tags
    • UND-Verknüpfung über ; und ODER-Verknüpfung über |. (Beispiel TAG1;TAG2;TAG3|TAG4)

Beispiel:

active:true tags:ProjectX;Finance|Controlling = Sucht alle aktiven Templates, welche entweder getaggt sind mit ProjectX und Finance oder welche den Tag Controlling haben.

OrganizationUnits​

Mögliche "Query"-Optionen:

  • title: Suche nach Titel
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • sid: Suche nach der SID
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.
  • field[<Org.FieldId>]: Suche nach einem konfigurierbaren Feld der Organisationseinheit (z.B. field[Org.Title])
    • Unterstützt den *-Wildcard Operator am Anfang und Ende.

Beispiel:

title:*Sales* sid:OU-123 = Sucht alle OrganizationUnits, deren Titel "Sales" enthält und deren SID OU-123 ist.


Antwortstruktur und Paginierung​

Die Listen-Endpunkte geben die Ergebnisse in einer einheitlichen Hülle zurück: Die eigentlichen Datensätze stehen unter data, die Paginierungsinformationen unter pagingDetails.

{
"data": [
{ "id": "…", "title": "…" }
],
"pagingDetails": {
"page": 1,
"pageSize": 10,
"totalPages": 5
}
}

Die Paginierung wird über die Query-Parameter page und pageSize gesteuert:

  • page — Standard 1.
  • pageSize — Standard 10, Minimum 10, Maximum 100 (Werte ausserhalb dieses Bereichs werden entsprechend angepasst).

Pfadangabe der Endpunkte​

Die Endpunkte sind über das Routen-Präfix /api/v3/{datasourceId}/Admin/… erreichbar. In einer Standard-Installation ist die Web API unter dem Host-Pfad /webapi eingebunden — die vollständige URL lautet daher https://{instanz}/webapi/api/v3/{datasourceId}/Admin/…. Die PowerShell-Beispiele auf dieser Seite verwenden diese vollständige Form.


Gemeinsame Endpunkte (/Common)​

Neben /Admin/… gibt es das Routen-Präfix /api/v3/{datasourceId}/Common/… für Abfragen, die sowohl von Admin-API- als auch von Connect-API-Clients benötigt werden. Sie sind bewusst nur einmal vorhanden, damit ein bestehender Client nicht zusätzlich für den jeweils anderen Bereich registriert werden muss.

EndpunktBeschreibung
GET .../Common/MetaTemplatesLiefert alle MetaTemplate-IDs mit ihrem Namen als Objekt (GUID → Name). Die IDs werden für die Suche nach metaTemplateId benötigt — sowohl in der Templates-Abfrage der Admin API als auch im templateQuery der Connect API. Die Connect-Abfrage berücksichtigt dabei nur die aktuellen Vorlagentypen (siehe Vorlagen abfragen).
GET .../Common/PrincipalsSucht Security Accounts (Benutzer, Gruppen, AppUserGroups) nach Namen — gleichzeitig in der primedocs-Datenbank und im angebundenen Verzeichnis (AD, Entra ID, SCIM). Liefert pro Treffer name, primarySid, type (User, Group, AppUserGroup), isOnboardedInDataSource sowie idInDataSource (Datenbank-ID, falls bereits onboarded). Damit lässt sich eine SID für das Onboarding oder eine Berechtigungsvergabe ermitteln, ohne das Verzeichnis separat abzufragen.

Query-Parameter von .../Common/Principals:

ParameterBeschreibung
query (erforderlich)Suchbegriff, mindestens 2 Zeichen.
limit (optional)Maximale Anzahl Treffer; Standard 20, Maximum 100.
types (optional)Kommaseparierte Liste der gesuchten Typen: User, Group, AppUserGroup. Standard: alle drei.
sources (optional)Kommaseparierte Liste der Quellen: DataSource (primedocs-Datenbank) und PrincipalConnector (angebundenes Verzeichnis). Standard: beide.
Token und Berechtigung

Die /Common-Endpunkte akzeptieren ein AccessToken mit dem Scope pd_AdminWebApi oder pd_ConnectWebApi (sowie das Token der Web App). Der Bezug des Tokens ist identisch zur Authentifizierung — lediglich der Pfad unterscheidet sich. Bei einem Client-Credentials-Token (Service Account ohne Benutzerkontext) wird die Datenquelle aus dem Pfad {datasourceId} aufgelöst; bei einem Benutzer-Token gelten dessen Datenquellen-Berechtigungen.

# Prepare headers for request
$apiRequestHeaders = @{
"Authorization" = "Bearer $accessToken"
}

# MetaTemplate-IDs abfragen
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Common/MetaTemplates"
$metaTemplates = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders
$metaTemplates.PSObject.Properties | ForEach-Object { Write-Output "$($_.Name): '$($_.Value)'" }

# Security Account suchen (nur Benutzer, nur im Verzeichnis)
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Common/Principals?query=muster&types=User&sources=PrincipalConnector"
$principals = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders
$principals | Format-Table name, primarySid, type, isOnboardedInDataSource

Beispiele​

Dieses AccessToken muss bei allen Aufrufen in den Authorization-Header mitgegeben werden. Die API erlaubt u.a. das Auflisten, Anlegen und Bearbeiten von Benutzern, Profilen, Gruppen, Organisationseinheiten und Snippet-Gruppen sowie das Abfragen von Vorlagen und AppUserGroups. Nachfolgend sind Beispiele zu finden:

Benutzer auflisten​

Damit werden vorhandene Benutzer aufgelistet:

# Prepare headers for request
$apiRequestHeaders = @{
"Authorization" = "Bearer $accessToken"
}

Write-Host "Getting users..."
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"

try {
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Admin/Users?pageSize=$($pageSize)&page=$($page)"
$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($user in $response.data) {
Write-Output "$($user.id): '$($user.title)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}

Benutzer-Onboarding​

Über diesen Aufruf kann ein neuer Benutzer anhand der SID hinzugefügt werden. Es wird dann automatisch der Benutzer Onboarding & Offboarding Prozess durchlaufen.

# Prepare headers for request
$apiRequestHeaders = @{
"Authorization" = "Bearer $accessToken"
}

$sid = Read-Host "Enter SID"
Write-Host "Creating and onboarding user with SID: $sid"

try {
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Admin/Users?sid=" + $sid;
$user = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $apiRequestHeaders
Write-Output "Onboarded '$($user.title)' with id '$($user.id)'";
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}

Berechtigungen auf Organisationseinheiten verwalten​

Über die Berechtigungen einer Organisationseinheit wird gesteuert, welche Benutzer, Gruppen oder AppUserGroups die Organisationseinheit verwenden dürfen. Die Admin API bietet dafür folgende Endpunkte:

EndpunktBeschreibung
GET .../Admin/OrganizationUnits/{organizationUnitId}Liefert die Details inkl. der Liste permissions. Jeder Eintrag enthält die id der Berechtigung sowie genau eine der IDs userId, groupId oder appUserGroupId.
POST .../Admin/OrganizationUnits/{organizationUnitId}/PermissionsFügt eine Berechtigung hinzu. Im Body genau eine der Eigenschaften UserId, GroupId oder AppUserGroupId angeben.
DELETE .../Admin/OrganizationUnits/{organizationUnitId}/Permissions/{permissionId}Entfernt die angegebene Berechtigung.

Beide schreibenden Endpunkte geben die aktualisierte Organisationseinheit inkl. ihrer Berechtigungen zurück.

  • Pro Security Account (Benutzer, Gruppe oder AppUserGroup) ist nur eine Berechtigung möglich. Um sie zu ändern, die bestehende Berechtigung zuerst entfernen und danach neu anlegen.
  • Beim Erstellen einer Organisationseinheit (POST .../Admin/OrganizationUnits) können Berechtigungen direkt über das optionale Array Permissions mitgegeben werden — je Eintrag genau eine der drei IDs, jeder Account höchstens einmal.
# Prepare headers for request
$apiRequestHeaders = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}

# Add a permission for a group
$body = @{ GroupId = "1de8e5a3-0d5f-4be3-b1ab-1e02c04efeb3" } | ConvertTo-Json
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Admin/OrganizationUnits/$($organizationUnitId)/Permissions"
$organizationUnit = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $apiRequestHeaders -Body $body
$organizationUnit.permissions | Format-Table

# Remove a permission
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Admin/OrganizationUnits/$($organizationUnitId)/Permissions/$($permissionId)"
$organizationUnit = Invoke-RestMethod -Uri $apiUrl -Method DELETE -Headers $apiRequestHeaders

Textbaustein-Metadaten verwalten​

Neben den Snippet-Gruppen lassen sich auch die Metadaten einzelner Textbausteine über die Admin API lesen und pflegen — als Grundlage für das Textbaustein-Management im Web-Admin. Verwaltet werden dabei ausschliesslich die Metadaten (Name, Schlüssel, Sortierung, AutoText, Berechtigungen und Lokalisierungen); Inhalt und Format eines Textbausteins werden über diese Endpunkte nur gelesen, nicht verändert.

Die Endpunkte liegen unter .../Admin/Snippets/{usage}/…. {usage} grenzt den Bereich ein und ist entweder public (allgemein verfügbare Textbausteine) oder designer (Textbausteine der Vorlagenerstellung).

EndpunktBeschreibung
GET .../Admin/Snippets/{usage}/{snippetId}Liefert einen Textbaustein mit Metadaten, Lokalisierungen (localized), Berechtigungen (permissions) und den vorhandenen Inhalts- und Formatangaben (data, schreibgeschützt).
POST .../Admin/Snippets/{usage}Legt einen neuen, rein metadatenbasierten Textbaustein an.
PUT .../Admin/Snippets/{usage}/{snippetId}Ändert die Metadaten (SnippetGroupId, Sort, Key, AutoTextName).
DELETE .../Admin/Snippets/{usage}/{snippetId}Löscht den Textbaustein.
POST .../Admin/Snippets/{usage}/{snippetId}/PermissionsFügt eine Berechtigung hinzu (im Body genau eine der IDs UserId, GroupId oder AppUserGroupId, dazu HasModifyPermission/HasUsingPermission).
DELETE .../Admin/Snippets/{usage}/{snippetId}/Permissions/{permissionId}Entfernt die angegebene Berechtigung.
POST .../Admin/Snippets/{usage}/{snippetId}/LocalizedFügt die Lokalisierung für eine Sprache hinzu (Name, Description, SearchKeywords, Lcid).
DELETE .../Admin/Snippets/{usage}/{snippetId}/Localized/{lcid}Entfernt die Lokalisierung der angegebenen Sprache (lcid).

Alle Endpunkte geben den aktualisierten Textbaustein zurück. Es gelten u.a. folgende Regeln:

  • Key ist optional, maximal 256 Zeichen und über alle Textbausteine hinweg eindeutig.
  • AutoTextName ist optional und maximal 32 Zeichen.
  • Sort ist ≥ 0 und innerhalb derselben übergeordneten Gruppe eindeutig; eine leere SnippetGroupId ordnet den Textbaustein direkt der obersten Ebene zu.
  • Pro Sprache (Lcid) ist nur eine Lokalisierung möglich, und pro Lokalisierung muss mindestens einer der Werte Name, Description oder SearchKeywords gesetzt sein.
  • Pro Security Account (Benutzer, Gruppe oder AppUserGroup) ist nur eine Berechtigung möglich.
hinweis

Diese Endpunkte erfordern die Rolle SysAdmin oder SnippetAdmin (bzw. einen entsprechend berechtigten Service Account). Siehe Authentifizierung.

$apiRequestHeaders = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}

# Metadaten eines Textbausteins lesen
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Admin/Snippets/public/$($snippetId)"
$snippet = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders
$snippet.localized | Format-Table

# Metadaten ändern (z.B. Schlüssel und Sortierung)
$body = @{ Key = "greeting-formal"; Sort = 0 } | ConvertTo-Json
$apiUrl = "https://{instanz}/webapi/api/v3/$($datasourceId)/Admin/Snippets/public/$($snippetId)"
$snippet = Invoke-RestMethod -Uri $apiUrl -Method PUT -Headers $apiRequestHeaders -Body $body

PowerShell Script​

Nachfolgend finden Sie ein vollständiges Beispiel-PowerShell-Script, welches verschiedene UseCases abdeckt: Benutzer, Profile und Profile-Shares, Gruppen, Organisationseinheiten, Snippet-Gruppen (inkl. Berechtigungen und Lokalisierungen), AppUserGroups sowie Templates.

Der Abschnitt Configuration (datasourceId, tokenUrl, baseApiUrl, clientId und clientSecret) muss auf die Einstellungen der jeweiligen Umgebung angepasst werden.

# Configuration
$datasourceId = "b78c3707-d7c7-4fc7-b97f-87d70f63c1ac"
$tokenUrl = "https://{instanz}/ids/connect/token"
$baseApiUrl = "https://{instanz}/webapi/api"
$clientID = "CustomApiClient"
$clientSecret = "CustomClient_Secret_123"
$scope = "pd_AdminWebApi"

$tokenRequestHeaders = @{
"Content-Type" = "application/x-www-form-urlencoded"
}
$tokenRequestBody = @{
client_id = $clientID
client_secret = $clientSecret
grant_type = "client_credentials"
scope = $scope
}


# Request the access token
try {
$tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method POST -Headers $tokenRequestHeaders -Body $tokenRequestBody
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
if (-not $tokenResponse.access_token) {
Write-Error "Failed to obtain an access token!"
exit 1
}

# Access token information
Write-Host "Access Token: $($tokenResponse.access_token)"
$accessToken = $tokenResponse.access_token

# Prepare headers for request
$apiRequestHeaders = @{
"Authorization" = "Bearer $accessToken"
}

$putBodyRequestHeaders = @{
"Content-Type" = "application/json"
"Authorization" = "Bearer $accessToken"
}

function Show-Menu {
Write-Host "================ Main Menu ================"
Write-Host "1: Get Users"
Write-Host "2: Get User Details"
Write-Host "3: Update User"
Write-Host "4: Create and Onboard User"

Write-Host "5: Get Profile"
Write-Host "6: Profile Update"
Write-Host "7: Add Profile Share"
Write-Host "8: Delete Profile Share"

Write-Host "9: Create and Onboard Group"
Write-Host "10: Get Groups"

Write-Host "11: Get Organization Units"
Write-Host "12: Get Organization Unit Details"
Write-Host "13: Get Organization Unit Children"
Write-Host "14: Update Organization Unit"
Write-Host "15: Create Organization Unit"
Write-Host "16: Delete Organization Unit"
Write-Host "29: Get Organization Unit Tree"
Write-Host "30: Add Organization Unit Permission"
Write-Host "31: Delete Organization Unit Permission"

Write-Host "17: Get Snippet Groups"
Write-Host "18: Get Snippet Group Details"
Write-Host "19: Create Snippet Group"
Write-Host "20: Delete Snippet Group"
Write-Host "21: Get Snippet Group Children"
Write-Host "22: Update Snippet Group ParentId or Sort"
Write-Host "23: Delete Snippet Group Permission"
Write-Host "24: Add Snippet Group Permission"
Write-Host "25: Delete Snippet Group Localization"
Write-Host "26: Add Snippet Group Localization"

Write-Host "27: Get AppUserGroups"

Write-Host "28: Get Templates"

Write-Host "Q: Exit"
}

function GetUsers {
Write-Host "Getting users..."
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
$query = Read-Host "Enter query"
try {


$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users?pageSize=$($pageSize)&page=$($page)"

# Append query only if it's not null or whitespace
if (![string]::IsNullOrWhiteSpace($query)) {
$apiUrl += "&query=$query"
}

$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($user in $response.data) {
Write-Output "$($user.id): '$($user.title)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetUserDetails {
$userId = Read-Host "Enter UserId"
Write-Host "Getting details for user: $userId"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users/" + $userId;
$user = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

Write-Output "Id: '$($user.id)'"
Write-Output "Title: '$($user.title)'";
Write-Output "Profiles: "
foreach ($profile in $user.profiles) {
Write-Output "'$($profile.id)': '$($profile.title) (Profile OU: '$($profile.organizationUnitId)')"
}
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function CreateAndOnBoardUser {
$sid = Read-Host "Enter SID"
Write-Host "Creating and onboarding user with SID: $sid"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users?sid=" + $sid;
$user = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $apiRequestHeaders
Write-Output "Onboarded '$($user.title)' with id '$($user.id)'";
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function CreateAndOnBoardGroup {
$sid = Read-Host "Enter SID"
Write-Host "Creating and onboarding Group with SID: $sid"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Groups?sid=" + $sid;
$group = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $apiRequestHeaders
Write-Output "Onboarded '$($group.title)' with id '$($group.id)'";
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetGroups {
Write-Host "Getting Groups..."
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
$query = Read-Host "Enter query"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Groups?pageSize=$($pageSize)&page=$($page)"

# Append query only if it's not null or whitespace
if (![string]::IsNullOrWhiteSpace($query)) {
$apiUrl += "&query=$query"
}

$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($group in $response.data) {
Write-Output "$($group.id): '$($group.title)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetAppUserGroups {
Write-Host "Getting AppUserGroups..."
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
$query = Read-Host "Enter query"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/AppUserGroups?pageSize=$($pageSize)&page=$($page)"

# Append query only if it's not null or whitespace
if (![string]::IsNullOrWhiteSpace($query)) {
$apiUrl += "&query=$query"
}

$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($group in $response.data) {
Write-Output "$($group.id): '$($group.title)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetTemplates {
Write-Host "Getting Templates..."
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
$query = Read-Host "Enter query"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Templates?pageSize=$($pageSize)&page=$($page)"

# Append query only if it's not null or whitespace
if (![string]::IsNullOrWhiteSpace($query)) {
$apiUrl += "&query=$query"
}

$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($template in $response.data) {
Write-Output "$($template.templateId): MetaTemplateId: '$($template.metaTemplateId)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function ProfileUpdate {
$userId = Read-Host "Enter User ID"
$profileId = Read-Host "Enter Profile ID"

$title = Read-Host "Enter Title"
$organizationUnitId = Read-Host "Enter New Organization Unit ID"
$lcid = 1031 #Read-Host "Enter lcid"
$field = "Org.Title" # Read-Host "Enter Field"
$field2 = "User.FirstName" # Read-Host "Enter Field"
$text = Read-Host "Enter New Org.Title Value (Empty = delete)"
$text2 = Read-Host "Enter New User.FirstName Value (Empty = delete)"

Write-Host "Updating profile for User ID: $userId, Profile ID: $profileId, Title: $title, Organization Unit ID: $organizationUnitId"

$targetOrganizationUnitId = if ($null -ne $organizationUnitId) {
[System.Guid]::Parse($organizationUnitId)
} else {
$null
}

try {
$body = @{
Title = $title;
OrganizationUnitId = $targetOrganizationUnitId;
FieldChanges = @(
@{
Lcid = $lcid
Field = $field
Text = $text
Purge = ($text -eq "")
},
@{
Lcid = $lcid
Field = $field2
Text = $text2
Purge = ($text2 -eq "")
}
)
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users/$($userId)/Profiles/$($profileId)";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method PUT -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetProfile {
$userId = Read-Host "Enter User ID"
$profileId = Read-Host "Enter Profile ID"
Write-Host "Getting profile for User ID: $userId, Profile ID: $profileId"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users/" + $userId + "/Profiles/" + $profileId;
$userProfile = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

Write-Output "Id: '$($userProfile.id)'"
Write-Output "Title: '$($userProfile.title)'";
Write-Output "ProfileShares: "
foreach ($share in $userProfile.profileShares) {
if ($null -ne $share.userId) {
Write-Output "'$($share.id)': UserId:'$($share.userId)', ProfilePermissionLevel:'$($share.profilePermissionLevel)', SignaturePermissionLevel:'$($share.signaturePermissionLevel)'"
}
if ($null -ne $share.groupId) {
Write-Output "'$($share.id)': GroupId:'$($share.groupId)', ProfilePermissionLevel:'$($share.profilePermissionLevel)', SignaturePermissionLevel:'$($share.signaturePermissionLevel)'"
}
if ($null -ne $share.appUserGroupId) {
Write-Output "'$($share.id)': AppUserGroupId:'$($share.appUserGroupId)', ProfilePermissionLevel:'$($share.profilePermissionLevel)', SignaturePermissionLevel:'$($share.signaturePermissionLevel)'"
}
}
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function AddProfileShare {
$userId = Read-Host "Enter User ID"
$profileId = Read-Host "Enter Profile ID"

Write-Host "Enter either User ID or Group ID or AppUserGroup ID to access the profile. Leave two of them empty."
$shareUserId = Read-Host "Enter User ID (or empty)"
$shareGroupId = Read-Host "Enter Group ID (or empty)"
$shareAppUserGroupId = Read-Host "Enter AppUserGroup ID (or empty)"

Write-Host " "
Write-Host "0: Profile share cannot be used as 'regular' profile"
Write-Host "1: Profile share can be used as 'regular' profile, but will be marked 'on behalf'"
Write-Host "2: Profile share can be used as 'regular' profile and impersonation is allowed"
$profilePermissionLevel = Read-Host "Enter Profile Permission Level"

Write-Host " "
Write-Host "0: Signature share cannot be used for document signing"
Write-Host "1: Signature share can be used for document signing, but without real signature image"
Write-Host "2: Signature share can be used for document signing with real signature image"
$signaturePermissionLevel = Read-Host "Enter Signature Permission Level"

Write-Host " "
Write-Host "0: Read-only (default) - profile can be used but not edited"
Write-Host "1: Read/write - profile can also be edited (data fields, signatures, organizational unit)"
$accessPermissionLevel = Read-Host "Enter Access Permission Level"

$targetShareUserId = if ($shareUserId -eq "") {
$null
} else {
$shareUserId
}

$targetShareGroupId = if ($shareGroupId -eq "") {
$null
} else {
$shareGroupId
}

$targetShareAppUserGroupId = if ($shareAppUserGroupId -eq "") {
$null
} else {
$shareAppUserGroupId
}

try {
$body = @{
UserId = $targetShareUserId
GroupId = $targetShareGroupId
AppUserGroupId = $targetShareAppUserGroupId
profilePermissionLevel = $profilePermissionLevel
signaturePermissionLevel = $signaturePermissionLevel
accessPermissionLevel = $accessPermissionLevel
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users/$($userId)/Profiles/$($profileId)/ProfileShares";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function DeleteProfileShare {
$userId = Read-Host "Enter User ID"
$profileId = Read-Host "Enter Profile ID"
$profileShareId = Read-Host "Enter Profile Share ID"

Write-Host "Deleting profile share for User ID: $userId, Profile ID: $profileId, Profile Share ID: $profileShareId"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users/$($userId)/Profiles/$($profileId)/ProfileShares/$($profileShareId)";
Invoke-RestMethod -Uri $apiUrl -Method DELETE -Headers $putBodyRequestHeaders
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetOrganizationUnits {
Write-Host "Getting organization units..."
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
$query = Read-Host "Enter query (optional, e.g. title:*Sales* or sid:OU-123)"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits?pageSize=$($pageSize)&page=$($page)";

# Append query only if it's not null or whitespace
if (![string]::IsNullOrWhiteSpace($query)) {
$apiUrl += "&query=$query"
}

$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($organizationUnit in $response.data) {
Write-Output "$($organizationUnit.id): '$($organizationUnit.title)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetOrganizationUnitDetails {
$organizationUnitId = Read-Host "Enter Organization Unit ID"
Write-Host "Getting details for organization unit: $organizationUnitId"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits/" + $organizationUnitId;
$organizationUnit = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

Write-Output "Id: '$($organizationUnit.id)'"
Write-Output "Title: '$($organizationUnit.title)'";
Write-Output "ParentId: '$($organizationUnit.parentId)'";
Write-Output "Fields:";
foreach ($field in $organizationUnit.fields) {
$inherited = if ($field.isInherited) { " (inherited)" } else { "" }
Write-Output " [$($field.lcid)] $($field.fieldId): '$($field.text)'$inherited"
}
Write-Output "Permissions:";
foreach ($permission in $organizationUnit.permissions) {
Write-Output " '$($permission.id)': UserId '$($permission.userId)' | GroupId '$($permission.groupId)' | AppUserGroupId '$($permission.appUserGroupId)'"
}
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}

}

function GetOrganizationUnitChildren {
$organizationUnitId = Read-Host "Enter Organization Unit ID"
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
$searchTerm = Read-Host "Enter title search term (optional)"
Write-Host "Getting children for organization unit: $organizationUnitId"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits/" + $organizationUnitId + "/Children?pageSize=$($pageSize)&page=$($page)";
if (![string]::IsNullOrWhiteSpace($searchTerm)) {
$query = [System.Uri]::EscapeDataString("title:*$searchTerm*")
$apiUrl += "&query=$query"
}
$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($organizationUnit in $response.data) {
Write-Output "$($organizationUnit.id): '$($organizationUnit.title)'"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}

}

function GetOrganizationUnitTree {
$searchTerm = Read-Host "Enter title search term (optional)"
Write-Host "Getting organization unit tree..."
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnitTree"
if (![string]::IsNullOrWhiteSpace($searchTerm)) {
$query = [System.Uri]::EscapeDataString("title:*$searchTerm*")
$apiUrl += "?query=$query"
}

$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders
$response | ConvertTo-Json -Depth 10
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function UpdateOrganizationUnit {
Write-Host "Updating organization unit"
$organizationUnitId = Read-Host "Enter Organization Unit ID"
$title = Read-Host "Enter New Title"
$parentId = Read-Host "Enter New Parent Organization Unit ID"
$sid = Read-Host "Enter New SID"
$lcid = 1031 #Read-Host "Enter lcid"
$field = "Org.Title" # Read-Host "Enter Field"
$field2 = "Org.Claim" # Read-Host "Enter Field"
$text = Read-Host "Enter New Org.Title Value (Empty = delete)"
$text2 = Read-Host "Enter New Org.Claim Value (Empty = delete)"


Write-Host "Updating organization unit, Title: $title, Organization Unit ID: $organizationUnitId"

$targetParentId = if ($null -ne $parentId) {
[System.Guid]::Parse($parentId)
} else {
$null
}

try {
$body = @{
Title = $title
ParentId = $targetParentId
Sid = $sid
FieldChanges = @(
@{
Lcid = $lcid
Field = $field
Text = $text
Purge = ($text -eq "")
},
@{
Lcid = $lcid
Field = $field2
Text = $text2
Purge = ($text2 -eq "")
}
)
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits/$($organizationUnitId)";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method PUT -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function CreateOrganizationUnit {
Write-Host "Creating organization unit"
$title = Read-Host "Enter Title"
$parentId = Read-Host "Enter Parent Organization Unit ID (leave empty for root)"
$sid = Read-Host "Enter SID (optional, leave empty to create without SID)"
$lcid = 1031 #Read-Host "Enter lcid"
$field = "Org.Title" # Read-Host "Enter Field"
$text = Read-Host "Enter Org.Title Value (leave empty to skip)"

$targetParentId = if (![string]::IsNullOrWhiteSpace($parentId)) {
[System.Guid]::Parse($parentId)
} else {
$null
}

$targetSid = if (![string]::IsNullOrWhiteSpace($sid)) { $sid } else { $null }

$fields = @()
if (![string]::IsNullOrWhiteSpace($text)) {
$fields += @{
Lcid = $lcid
Field = $field
Text = $text
}
}

try {
$body = @{
Title = $title
ParentId = $targetParentId
Sid = $targetSid
Fields = $fields
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

$newId = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $putBodyRequestHeaders -Body $utf8body
Write-Output "Created OrganizationUnit with ID: $newId"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function DeleteOrganizationUnit {
Write-Host "Deleting organization unit"
$organizationUnitId = Read-Host "Enter Organization Unit ID"
$deleteChildrenInput = Read-Host "Delete children as well? (y/n, default: n)"
$deleteChildren = ($deleteChildrenInput -eq "y")

Write-Host "Deleting organization unit: $organizationUnitId (deleteChildren: $deleteChildren)"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits/$($organizationUnitId)?deleteChildren=$($deleteChildren)";
Invoke-RestMethod -Uri $apiUrl -Method DELETE -Headers $apiRequestHeaders
Write-Output "Deleted OrganizationUnit: $organizationUnitId"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function AddOrganizationUnitPermission {
$organizationUnitId = Read-Host "Enter Organization Unit ID"

Write-Host "Enter either User ID or Group ID or AppUserGroup ID to allow using the organization unit. Leave two of them empty."
$shareUserId = Read-Host "Enter User ID (or empty)"
$shareGroupId = Read-Host "Enter Group ID (or empty)"
$shareAppUserGroupId = Read-Host "Enter AppUserGroup ID (or empty)"

$targetUserId = if ($shareUserId -eq "") { $null } else { $shareUserId }
$targetGroupId = if ($shareGroupId -eq "") { $null } else { $shareGroupId }
$targetAppUserGroupId = if ($shareAppUserGroupId -eq "") { $null } else { $shareAppUserGroupId }

try {
$body = @{
UserId = $targetUserId
GroupId = $targetGroupId
AppUserGroupId = $targetAppUserGroupId
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits/$($organizationUnitId)/Permissions";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

$organizationUnit = Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $putBodyRequestHeaders -Body $utf8body
Write-Output "Permissions:"
foreach ($permission in $organizationUnit.permissions) {
Write-Output " '$($permission.id)': UserId '$($permission.userId)' | GroupId '$($permission.groupId)' | AppUserGroupId '$($permission.appUserGroupId)'"
}
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function DeleteOrganizationUnitPermission {
$organizationUnitId = Read-Host "Enter Organization Unit ID"
$permissionId = Read-Host "Enter Permission ID"

Write-Host "Deleting permission $permissionId on organization unit: $organizationUnitId"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/OrganizationUnits/$($organizationUnitId)/Permissions/$($permissionId)";
Invoke-RestMethod -Uri $apiUrl -Method DELETE -Headers $apiRequestHeaders
Write-Output "Deleted permission: $permissionId"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function UpdateUser {
$userId = Read-Host "Enter User ID"
$title = Read-Host "Enter New Title"
$lcid = 1031 #Read-Host "Enter lcid"
$field = "User.FirstName" # Read-Host "Enter Field"
$field2 = "User.LastName" # Read-Host "Enter Field"
$text = Read-Host "Enter New User.FirstName Value (Empty = delete)"
$text2 = Read-Host "Enter New User.LastName Value (Empty = delete)"

Write-Host "Updating user, Title: $title, User ID: $userId"

try {
$body = @{
Title = $title
FieldChanges = @(
@{
Lcid = $lcid
Field = $field
Text = $text
Purge = ($text -eq "")
},
@{
Lcid = $lcid
Field = $field2
Text = $text2
Purge = ($text2 -eq "")
}
)
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/Users/$($userId)";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method PUT -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetSnippetGroups {
Write-Host "Getting snippet groups (public)..."
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/?pageSize=$($pageSize)&page=$($page)";
$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($snippetGroup in $response.data) {
Write-Output "$($snippetGroup.id)"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetSnippetGroupsChildren {
Write-Host "Getting snippet groups (public)..."
$parentSnippetGroup = Read-Host "Enter Parent Snippet Group"
$pageSize = Read-Host "Enter pagesize"
$page = Read-Host "Enter page"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($parentSnippetGroup)/SnippetGroups?pageSize=$($pageSize)&page=$($page)";
$response = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

foreach ($snippetGroup in $response.data) {
Write-Output "$($snippetGroup.id)"
}
Write-Output "Page: $($response.pagingDetails.page) / $($response.pagingDetails.totalPages)"
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function GetSnippetGroupDetails {
Write-Host "Getting snippet groups (public) for id..."
$snippetGroup = Read-Host "Enter Snippet Group ID"
try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($snippetGroup)";
$snippetGroup = Invoke-RestMethod -Uri $apiUrl -Method GET -Headers $apiRequestHeaders

Write-Output "Id: '$($snippetGroup.id)'"
Write-Output "ParentId: '$($snippetGroup.parentId)'"
Write-Output "Sort: '$($snippetGroup.sort)'"

Write-Output "Localized Data:"

foreach ($localized in $snippetGroup.localized) {
Write-Output "Localized '$($localized.lcid)': Name '$($localized.name)' | Description '$($localized.description)' | SearchKeywords '$($localized.searchkeywords)'"
}

Write-Output "Permissions:"

foreach ($permission in $snippetGroup.permissions) {
Write-Output "Permission '$($permission.id)': UserId '$($permission.userId)' | GroupId '$($permission.groupid)' | AppUserGroupId '$($permission.appUserGroupId)' | HasModifyPermission: '$($permission.HasModifyPermission)' | HasUsingPermission: '$($permission.HasUsingPermission)'"
}
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function CreateSnippetGroup {
$parentId = Read-Host "Enter Snippet Parent Id (or empty)"

Write-Host "Enter either User ID or Group ID or AppUserGroup ID to give use and modify permission on the snippetgroup. Leave two of them empty."
$shareUserId = Read-Host "Enter User ID (or empty)"
$shareGroupId = Read-Host "Enter Group ID (or empty)"
$shareAppUserGroupId = Read-Host "Enter AppUserGroup ID (or empty)"

$targetShareUserId = if ($shareUserId -eq "") {
$null
} else {
$shareUserId
}

$targetShareGroupId = if ($shareGroupId -eq "") {
$null
} else {
$shareGroupId
}

$targetShareAppUserGroupId = if ($shareAppUserGroupId -eq "") {
$null
} else {
$shareAppUserGroupId
}

$targetParentSnippetGroupId = if ($parentId -eq "") {
$null
} else {
[System.Guid]::Parse($parentId)
}

$lcid = Read-Host "Enter lcid"
$name = Read-Host "Enter Sample Name"

# Sort can also be applied

try {
$body = @{
ParentId = $targetParentSnippetGroupId
Localized = @(
@{
Lcid = $lcid
Name = $name
}
)
Permissions = @(
@{
UserId = $targetShareUserId
GroupId = $targetShareGroupId
AppUserGroupId = $targetShareAppUserGroupId
HasModifyPermission = $true
HasUsingPermission = $true
}
)

}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function DeleteSnippetGroup {
$snippetGroup = Read-Host "Enter SnippetGroup ID"

Write-Host "Deleting public snippet group (and everything below) for Snippet Group ID: $snippetGroup"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($snippetGroup)";
Invoke-RestMethod -Uri $apiUrl -Method DELETE -Headers $putBodyRequestHeaders
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function UpdateSnippetGroup {
$targetSnippetGroup = Read-Host "Enter Snippet Group Id which needs to be updated"
$parentId = Read-Host "Enter new Snippet Group Parent Id"
$sort = Read-Host "Enter Sort"

$targetParentSnippetGroupId = if ($parentId -eq "") {
$null
} else {
[System.Guid]::Parse($parentId)
}

try {
$body = @{
ParentId = $targetParentSnippetGroupId
Sort = $sort
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($targetSnippetGroup)";

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method PUT -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function DeleteSnippetGroupPermission {
$targetSnippetGroup = Read-Host "Enter Snippet Group Id which needs to be updated"
$targetSnippetGroupPermissionId = Read-Host "Enter Permission Id"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($targetSnippetGroup)/Permissions/$($targetSnippetGroupPermissionId)";
Invoke-RestMethod -Uri $apiUrl -Method DELETE -Headers $putBodyRequestHeaders
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function AddSnippetGroupPermission {
$targetSnippetGroupId = Read-Host "Enter Snippet Group Id"

Write-Host "Enter either User ID or Group ID or AppUserGroup ID to give use and modify permission on the snippetgroup. Leave two of them empty."
$shareUserId = Read-Host "Enter User ID (or empty)"
$shareGroupId = Read-Host "Enter Group ID (or empty)"
$shareAppUserGroupId = Read-Host "Enter AppUserGroup ID (or empty)"

$targetShareUserId = if ($shareUserId -eq "") {
$null
} else {
$shareUserId
}

$targetShareGroupId = if ($shareGroupId -eq "") {
$null
} else {
$shareGroupId
}

$targetShareAppUserGroupId = if ($shareAppUserGroupId -eq "") {
$null
} else {
$shareAppUserGroupId
}

try {
$body = @{
UserId = $targetShareUserId
GroupId = $targetShareGroupId
AppUserGroupId = $targetShareAppUserGroupId
HasModifyPermission = $true
HasUsingPermission = $true
}
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($targetSnippetGroupId)/Permissions"

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function DeleteSnippetGroupLocalization {
$targetSnippetGroup = Read-Host "Enter Snippet Group Id which needs to be updated"
$targetSnippetGroupLcid = Read-Host "Enter Localization LCID"

try {
$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($targetSnippetGroup)/Localized/$($targetSnippetGroupLcid)";
Invoke-RestMethod -Uri $apiUrl -Method DELETE -Headers $putBodyRequestHeaders
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}

function AddSnippetGroupLocalization {
$targetSnippetGroupId = Read-Host "Enter Snippet Group Id"

$lcid = Read-Host "Enter lcid"
$name = Read-Host "Enter Name"
$description = Read-Host "Enter Description"
$searchKeyWord = Read-Host "Enter SearchKeywords"


try {
$body = @{
Lcid = $lcid
Name = $name
Description = $description
SearchKeywords = $searchKeyWord
}

$apiUrl = "$($baseApiUrl)/v3/$($datasourceId)/Admin/SnippetGroups/Public/$($targetSnippetGroupId)/Localized"

# Ensure UTF-8 Encoding
$utf8body = ([System.Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json)))

Invoke-RestMethod -Uri $apiUrl -Method POST -Headers $putBodyRequestHeaders -Body $utf8body
}
catch {
Write-Error "Error making the request: $_"
exit 1;
}
}


do {

Show-Menu
$selection = Read-Host "Please select an option"

switch ($selection) {
'1' { GetUsers }
'2' { GetUserDetails }
'3' { UpdateUser }
'4' { CreateAndOnBoardUser }

'5' { GetProfile }
'6' { ProfileUpdate }
'7' { AddProfileShare }
'8' { DeleteProfileShare }

'9' { CreateAndOnBoardGroup }
'10' { GetGroups }

'11' { GetOrganizationUnits }
'12' { GetOrganizationUnitDetails }
'13' { GetOrganizationUnitChildren }
'14' { UpdateOrganizationUnit }
'15' { CreateOrganizationUnit }
'16' { DeleteOrganizationUnit }
'29' { GetOrganizationUnitTree }
'30' { AddOrganizationUnitPermission }
'31' { DeleteOrganizationUnitPermission }

'17' { GetSnippetGroups }
'18' { GetSnippetGroupDetails }
'19' { CreateSnippetGroup }
'20' { DeleteSnippetGroup }
'21' { GetSnippetGroupsChildren }
'22' { UpdateSnippetGroup }
'23' { DeleteSnippetGroupPermission }
'24' { AddSnippetGroupPermission }
'25' { DeleteSnippetGroupLocalization }
'26' { AddSnippetGroupLocalization }

'27' { GetAppUserGroups }

'28' { GetTemplates }

'Q' { break; }
Default {
Write-Host "Invalid option selected"
}
}
} while ($selection -ne 'Q')

Fehlerbehandlung​

Die HTTP-Statuscodes und das Fehler-Response-Format sind einheitlich unter API → Fehlerbehandlung beschrieben. Fehlende Rechte (Rolle SysAdmin bzw. OrganisationAdmin) ergeben 403 Forbidden, eine unbekannte datasourceId ergibt 404 Not Found.

Swagger / Open API​

Die aktuelle Admin API Open API kann z.B. von der PrimeSoft Instanz als Referenz genutzt werden:

https://primesoft.primedocs.io/webapi/swagger/index.html

Sie können diese Beschreibung z.B. über den Swagger Editor visualisieren.