VC Publisher API

Übersicht

Der VC Publisher bietet eine REST API. Jede Funktion der Benutzeroberfläche ist auch über die REST API verfügbar — die Benutzeroberfläche baut selbst vollständig auf der REST API auf. Das bedeutet: Alles, was Sie in der Benutzeroberfläche tun können, lässt sich auch programmatisch über die API automatisieren oder integrieren.

Die interaktive API-Dokumentation (Swagger UI) ist unter folgender URL verfügbar:

https://{publisherUrl}/apidoc/v1/#

Die {publisherUrl} muss durch die tatsächliche URL Ihrer VC Publisher-Instanz ersetzt werden. Alle Endpunkte können direkt im Browser durchsucht und getestet werden. Bei der Verwendung der Swagger UI klicken Sie auf die Schaltfläche „Try it out" und füllen Sie die erforderlichen Informationen für den jeweiligen Endpunkt aus. Die folgenden Abschnitte enthalten Beispiel-Workflows für häufige Anwendungsfälle und zeigen Schritt für Schritt, wie Sie mit der API interagieren können.

Die meisten Listenendpunkte sind paginiert und geben standardmäßig nur die ersten 20 Einträge zurück. Verwenden Sie die Query-Parameter limit und page, um durch die Ergebnisse zu navigieren (z. B. ?limit=50&page=1). Die Antwort enthält immer die Felder totalCount und totalPages.

JavaScript SDK

Aus der API-Spezifikation wird ein SDK generiert, die für eine einfachere Integration verwendet werden kann. Jedem API-Endpunkt entspricht eine Funktion, die nach der Anfragemethode und dem Endpunkt-Pfad im Camel-Case-Format benannt ist, z. B. wird POST /api/v1/login zu postLogin(), GET /api/v1/projects zu getProjects() usw.

Die SDK ist als npm-Paket verfügbar und kann mit folgendem Befehl installiert werden:

npm install @vcsuite/publisher-sdk

Zur Einrichtung der SDK muss die Server-URL einmalig gesetzt werden:

import { setServerUrl } from '@vcsuite/publisher-sdk';

setServerUrl('https://{publisherUrl}');

Authentifizierung

Jeder API-Endpunkt außer den Login-Endpunkten erfordert ein gültiges Bearer-Token. Das Token wird durch den Login-Vorgang erhalten und muss im Authorization-Header jeder nachfolgenden Anfrage enthalten sein. Ohne ein gültiges Token antwortet die API mit 401 Unauthorized.

Klicken Sie in der Swagger UI auf die Schaltfläche „Authorize" und geben Sie das Token ein, um alle über die Oberfläche gestellten Anfragen zu authentifizieren.

Bei der Verwendung von Shell-Befehlen mit curl fügen Sie das Token in den Header ein.

Bei der Verwendung des JavaScript SDK müssen Sie authorize einmalig mit dem Token aufrufen:

import { authorize } from '@vcsuite/publisher-sdk';

authorize(token);

Workflow 1: Login & Authentifizierung

Je nach Anwendungsfall gibt es zwei Anmeldemethoden: API-Token-Login für den programmatischen Zugriff und sitzungsbasierter Login für den UI-Zugriff.

API-Token-Login

Schritt 1 – Token abrufen

Senden Sie eine POST-Anfrage an /api/v1/login mit Benutzername und Passwort:

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "ihr-benutzername",
    "password": "ihr-passwort"
  }'
import { postLogin } from '@vcsuite/publisher-sdk';

const response = await postLogin({
  username: 'ihr-benutzername',
  password: 'ihr-passwort'
});

Bei der Verwendung des Login-Endpunkts in der Swagger UI muss "algorithm": "sha-256" entfernt werden, wenn das Passwort im Klartext eingegeben wird.

Eine erfolgreiche Antwort gibt 200 OK zurück:

{
  "_id": "64abc...",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6...",
  "tokenExpires": "2026-03-12T10:00:00.000Z"
}

Das Feld token ist das Bearer-Token. Das Feld tokenExpires gibt an, wann es ungültig wird.

Schritt 2 – Token verwenden

Fügen Sie das Token in den Authorization-Header jeder Anfrage ein. Als Beispiel wird hier abgerufen, wie Informationen zu allen Benutzerprofilen abgefragt werden:

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/user-profiles \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getUserProfiles } from '@vcsuite/publisher-sdk';

const user = await getUserProfiles({});

Abmelden

Um die aktuelle Sitzung oder das Token zu invalidieren:

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/logout \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getLogout } from '@vcsuite/publisher-sdk';

const response = await getLogout();

Workflow 2: Projekt erstellen

Erfordert die Super-User-Rolle.

Schritt 1 – Projekt erstellen

Zum Erstellen eines Projekts wird der Endpunkt POST /api/v1/project verwendet. Es müssen ein Name, eine Beschreibung und eine Bounding Box angegeben werden.

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mein Beispielprojekt",
    "description": "Ein Projekt zur Demonstration der API",
    "bbox": [-180, -85, 180, 85]
  }'
import { postProject } from '@vcsuite/publisher-sdk';

const response = await postProject(
  {
    // optional managerId
  },
  {
    name: 'My Example Project',
    description: 'A project for demonstrating the API',
    bbox: [-180, -85, 180, 85]
  }
);

Der optionale Query-Parameter managerId weist einen bestimmten Benutzer als Projektmanager zu. Wird er weggelassen, wird der anfragende Benutzer zum Manager.

Eine erfolgreiche Antwort gibt 201 Created zurück:

{
  "_id": "969b26df-ab3...",
  "createdAt": "2026-03-11T11:38:45.156Z",
  "createdBy": "64abc...",
  "updatedAt": "2026-03-11T11:38:45.156Z",
  "updatedBy": "64abc...",
  "name": "Mein Beispielprojekt",
  "description": "Ein Projekt zur Demonstration der API",
  "bbox": [
    -180,
    -85,
    180,
    85
  ],
  "properties": {
  },
  "defaultDataBucketId": "816d4486-f5a..."
}

Schritt 2 – Vorhandene Projekte abrufen

Um ein bestimmtes Projekt anhand seiner ID abzurufen, verwenden Sie den Endpunkt GET /api/v1/project/{projectId}.

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/project/{projectId} \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getProject } from '@vcsuite/publisher-sdk';

const project = await getProject({ projectId });

Die Rückgabe sieht genauso aus wie die Antwort in Schritt 1.

Um alle Projekte aufzulisten, auf die der authentifizierte Benutzer Zugriff hat, verwenden Sie den Endpunkt GET /api/v1/projects. Die Anfrage erlaubt verschiedene Query-Parameter zum Filtern und Sortieren der Ergebnisse. Die Parameter limit und page steuern die Paginierung, die Parameter sort und orderBy die Sortierung. Diese Parameter steuern die Form der Ausgabe und sind Teil der meisten Listenendpunkte. Die Projektliste unterstützt außerdem spezifische Parameter zum Filtern nach name, description, createdAt, createdBy, updatedAt, updatedBy und bbox.

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/projects \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getProjects } from '@vcsuite/publisher-sdk';

const projects = await getProjects({});

Workflow 3: Benutzer einem Projekt zuweisen

Erfordert die MANAGER-Berechtigung für das Projekt.

Benutzer müssen einem Projekt explizit zugewiesen werden, bevor sie mit ihm interagieren können. Jede Zuweisung verbindet einen Benutzer mit einer Rolle.

Schritt 1 – Benutzer-ID ermitteln

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/users \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getUsers } from '@vcsuite/publisher-sdk';

const users = await getUsers({});

Der Users-Endpunkt gibt alle Benutzer im System zurück, wenn der Benutzer Administratorrechte hat. Für Benutzer, die nur Projektmanager sind, gibt es den User-Profiles-Endpunkt. Dieser Endpunkt gibt alle Benutzer im System mit eingeschränkten Informationen zurück (ID und Name).

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/user-profiles \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getUserProfiles } from '@vcsuite/publisher-sdk';

const userProfiles = await getUserProfiles({});

Beide Endpunkte bieten eine Filteroption für den username. Der Users-Endpunkt bietet zusätzlich Filter für email, createdAt, createdBy, updatedAt und updatedBy. Die Rückgabe für Users sieht folgendermaßen aus:

{
  "items": [
    {
      "_id": "v6WEM...",
      "createdAt": "2016-02-10T15:46:35.816Z",
      "updatedAt": "2025-08-21T07:35:09.841Z",
      "updatedBy": "v6WEM...",
      "username": "benutzername",
      "email": "benutzer@email.de"
    },
    ...
    ]
}

Die Rückgabe für User-Profiles sieht folgendermaßen aus:

{
  "items": [
    {
      "_id": "v6WEM...",
      "username": "benutzername"
    },
    ...
    ]
}

Beide liefern eine ID, die in Schritt 3 für die Zuweisung eines Benutzers zu einem Projekt benötigt wird.

Schritt 2 – Verfügbare Rollen abrufen

Um einen Benutzer einem Projekt zuzuweisen, muss eine Rolle für den Benutzer angegeben werden. Die verfügbaren Rollen können mit folgendem Endpunkt abgerufen werden:

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/iam/roles \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getIamRoles } from '@vcsuite/publisher-sdk';

const roles = await getIamRoles({});

Die Rollen können mit den Standard-Tabellenfiltern und einem Berechtigungsfilter gefiltert werden. Dieser Filter beschreibt die Fähigkeit der Rolle (z. B. getProject). Die Rolle, die dem Benutzer in einem Projekt zugewiesen werden soll, sollte projektbezogen sein. Der Benutzer in einem Projekt sollte mindestens getProject-Berechtigungen haben. Auf dieser Grundlage werden nur zwei mögliche Rollen zurückgegeben: ProjectMember und ProjectManager. Die Rolle ProjectManager umfasst alle projektbezogenen Berechtigungen, während die Rolle ProjectMember hauptsächlich Leseberechtigungen enthält.

{
  "items": [
    {
      "_id": "84e1b02c-2b...",
      "createdAt": "2023-09-06T08:04:23.379Z",
      "updatedAt": "2026-01-15T08:08:43.385Z",
      "createdBy": "internal",
      "updatedBy": "internal",
      "name": "projectManager",
      "permissions": [
        "getProject",
        "getDatasource",
        "publishDatasource",
        "getUser",
        "getACL",
        "getCredentials",
        "createApp",
        "createModule",
        "editProject",
        "createDatasource",
        "deleteDatasource",
        "editDatasource",
        "createDatabase",
        "getDatabase",
        "deleteDatabase",
        "accessDbImport",
        "accessDbExport",
        "accessDbDelete",
        "accessObjectJob",
        "accessApplyUpdateJob",
        "accessObliqueJob",
        "accessPanoramaJob",
        "accessPointcloudJob",
        "accessSolarJob",
        "accessTerrainJob",
        "accessTMSJob",
        "accessCityDbInfo",
        "grantRole",
        "revokeRole",
        "getJob",
        "abortJob",
        "createDataBucket",
        "getDataBucket",
        "editDataBucket",
        "uploadToDataBucket",
        "deleteDataBucket",
        "getApp",
        "editApp",
        "deleteApp",
        "publishApp",
        "setAppPublic",
        "getModule",
        "editModule",
        "deleteModule"
      ]
    },
    {
      "_id": "be48df30-40...",
      "createdAt": "2023-09-06T08:04:23.381Z",
      "updatedAt": "2023-09-06T08:04:23.381Z",
      "createdBy": "internal",
      "updatedBy": "internal",
      "name": "projectMember",
      "permissions": [
        "getProject",
        "getDatasource",
        "publishDatasource",
        "getUser",
        "getACL",
        "getCredentials",
        "createScenario",
        "createApp",
        "createModule"
      ]
    }
  ],
  "limit": 20,
  "page": 0,
  "totalCount": 2,
  "totalPages": 1
}

Schritt 3 – Benutzer zuweisen

Wenn die erforderlichen Voraussetzungen erfüllt sind (userId, projectId und roleId), kann der Benutzer mit folgendem Endpunkt dem Projekt zugewiesen werden.

  • SHELL

  • JavaScript

curl -X PUT https://{publisherUrl}/api/v1/project/{projectId}/user/{userId} \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{ "roleId": "<role-id-aus-schritt-2>" }'
import { putProjectUser } from '@vcsuite/publisher-sdk';

await putProjectUser({ projectId, userId }, { roleId: '<role-id-aus-schritt-2>' });

Eine erfolgreiche Antwort ist 204 No Content.

Schritt 4 – Zuweisung überprüfen

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/project/{projectId}/users \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getProjectUsers } from '@vcsuite/publisher-sdk';

const users = await getProjectUsers({ projectId });

Dieser Endpunkt gibt eine Liste aller dem Projekt zugewiesenen Benutzer zurück, einschließlich ihrer Rollen.

Benutzer aus einem Projekt entfernen

  • SHELL

  • JavaScript

curl -X DELETE https://{publisherUrl}/api/v1/project/{projectId}/user/{userId} \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { deleteProjectUser } from '@vcsuite/publisher-sdk';

await deleteProjectUser({ projectId, userId });

Dieser Endpunkt ermöglicht es, einen Benutzer aus einem Projekt zu entfernen. Hängen Sie ?purge=true an, um in derselben Operation auch alle Gastapp-Berechtigungen zu entfernen.

Workflow 4: Einen Verarbeitungsjob ausführen

Eine Aufgabe (Task) definiert, was verarbeitet werden soll und wann. Ein Job ist die eigentliche Ausführungsinstanz, die beim Ausführen der Aufgabe erstellt wird. Die Swagger-UI dokumentiert die Job-Parameter nicht direkt. Um die verfügbaren Parameter für einen bestimmten Jobtyp zu ermitteln, kann man die Tasks in der Publisher-Benutzeroberfläche heranziehen. Ein Task kann über die Publisher-Benutzeroberfläche gestartet werden, und auf der Registerkarte „Netzwerk“ der Entwicklertools des Browsers lässt sich der API-Aufruf zum Erstellen der Aufgabe mit allen Parametern einsehen. Diese Parameter können dann verwendet werden, um Tasks direkt über die API zu erstellen.

Schritt 1 – Tasks erstellen

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project/{projectId}/task \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{
    "labels": [],
    "tags": {},
    "debugLevel": 2,
    "priority": 1,
    "name": "Test_api_task",
    "description": "task with api settings",
    "parameters": {
      ...
    },
    "properties": {},
    "jobType": "vcTilesVector",
    "jobVersion": "",
    "schedule": { "type": "immediate" }
  }'
import { postProjectTask } from '@vcsuite/publisher-sdk';

const response = await postProjectTask({ projectId }, {
  labels: [],
  tags: {},
  debugLevel: 2,
  priority: 1,
  name: 'Test_api_task',
  description: 'task with api settings',
  parameters: {
    datasource: { command: 'create', name: 'Vector_Test' },
    options: {
      input: {
        dataSource: {
          '@type': 'GeoJSONSource',
          fileSet: [{ dir: 'C:\\path\\to\\input\\data', fileName: [{ name: '*.json' }] }],
          extrudeInfo: { extrudePoints: false, extrudeLines: false, extrudePolygons: false, heightPropertyName: '', defaultExtrudedHeight: 0 },
          defaultColor: { '@type': 'ColorSymbol', value: '#cccccc' }
        },
        heightMode: { type: 'absolute', offset: 0 }
      },
      modelOptions: {
        defaultShininess: 0.2,
        defaultCreaseAngle: 10,
        renderPrimitiveOutlines: { value: false, color: '#000000', outlineMode: 'Surfaces', polygonArray: true }
      },
      tiling: {
        geometricErrorComputationStrategy: { '@type': 'GeometricErrorComputationRelativeToTileSizeStrategy', geometricErrorToTileSizeRatio: 0.0115866254 },
        value: {
          '@type': 'SingleLevelTiling',
          spatialSubdivisionSchema: { '@type': 'QuadtreeSubdivision' },
          fixedGeneralization: { '@type': 'FixedGeneralization', tolerance: 0, texelSize: 0 },
          fixedObjectSizeFilter: { '@type': 'FixedObjectSizeFilter', thresholdValue: 0 },
          tileLevel: 15
        },
        featureSelectionMode: 'containsCenter'
      },
      processing: { convertMaterialsToTextures: false },
      output: {
        tiles3D_1_1: {
          layerJson: { maxLevelsInTileset: 3, prettyPrint: true },
          gltfOptions: {
            exportMetadata: true, addSubfeaturesIndicator: true, backFaceCulling: true,
            transparencyMode: 'combined', alphaFilterThreshold: 0.8, metallicFactor: 0,
            minFilter: 'linear', magFilter: 'linear', prettyPrint: true, reverseFeatureIdLabels: true,
            srgbValuesInPbrBaseColorFactor: false, usePrimitiveOutlineExtension: true,
            useMaterialsUnlitExtension: false, useUnsignedShortIndexAccessors: false,
            imageEncoding: 'jpeg_png',
            jpegOptions: { jpegCompressionQuality: 0.8, jpegChromaSubsampling: '4_2_2' },
            pngOptions: { pngCompressionQuality: 0.5 }
          }
        }
      }
    }
  },
  properties: {},
  jobType: 'vcTilesVector',
  jobVersion: '',
  schedule: { type: 'immediate' }
});

Das Feld jobType bestimmt den Typ der Verarbeitung. Das Objekt parameters ist jobtyp-spezifisch.

Das Feld schedule steuert, wann der Job ausgeführt wird:

Schedule-Wert Verhalten

{ "type": "immediate" }

Der Job wird ausgeführt, sobald ein Verarbeitungs-Runner verfügbar ist

{ "type": "scheduled", "scheduled": "2026-03-12T08:00:00Z" }

Der Job wird zu einem bestimmten UTC-Datum und einer bestimmten Uhrzeit ausgeführt

{ "type": "cron", "cron": "0 3 * * *" }

Der Job wiederholt sich nach einem CRON-Zeitplan

Eine erfolgreiche Antwort gibt 200 OK mit dem erstellten Task-Objekt einschließlich seiner _id zurück.

{
  "jobVersion": "",
  "priority": 1,
  "debugLevel": 2,
  "tags": {},
  "labels": [],
  "properties": {},
  "name": "Test_api_task",
  "description": "task with api settings",
  "jobType": "vcTilesVector",
  "schedule": {
    "type": "immediate"
  },
  "projectId": "b68056fc-86ed-4681-...",
  "createdAt": "2026-03-12T13:59:38.664Z",
  "updatedAt": "2026-03-12T13:59:38.664Z",
  "createdBy": "v6WEM2A92...",
  "updatedBy": "v6WEM2A92...",
  "_id": "07047f43-26ed-4a40-...",
  "lastJobId": "954b1c80-7917-4ca0-...",
  "parameters": { ... },
}

Workflow 5: Daten hochladen & Datenquelle erstellen

Teil A – Daten in einen Data Bucket hochladen

Ein Data Bucket ist ein Speichercontainer innerhalb eines Projekts. Jedes Projekt hat einen Standard-Data-Bucket, der automatisch zusammen mit dem Projekt erstellt wird.

Hochgeladene Dateien werden nicht automatisch verwaltet. Es liegt in der Verantwortung des Benutzers, Dateien zu organisieren, zu aktualisieren und zu löschen. Es gibt kein Lifecycle-Management — Dateien verbleiben im Bucket, bis sie explizit gelöscht werden.

Neben dem Standard-Bucket können weitere Data Buckets erstellt und einem Projekt zugewiesen werden:

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project/{projectId}/data-bucket \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Mein eigener Bucket" }'
import { postProjectDataBucket } from '@vcsuite/publisher-sdk';

const bucket = await postProjectDataBucket({ projectId }, { name: 'Mein eigener Bucket' });

Eine erfolgreiche Antwort gibt 201 Created mit dem neuen Data-Bucket-Objekt zurück, einschließlich seiner _id, die in nachfolgenden Anfragen als {dataBucketId} verwendet werden kann.

Schritt 1 – Ziel-Data-Bucket ermitteln

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/project/{projectId}/data-buckets \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getProjectDataBuckets } from '@vcsuite/publisher-sdk';

const buckets = await getProjectDataBuckets({ projectId });

Die Antwort enthält eine Liste aller Data Buckets im Projekt, einschließlich selbst erstellter.

{
  "items": [
    {
      "_id": "57d6913d-af53-4292-...",
      "properties": {},
      "name": "default-b68056fc-86ed-...",
      "createdAt": "2026-01-08T09:15:15.741Z",
      "updatedAt": "2026-01-08T09:15:15.741Z",
      "createdBy": "v6WEM2A92ozfZaAu5",
      "updatedBy": "v6WEM2A92ozfZaAu5",
      "projectId": "b68056fc-86ed-4681-..."
    }
  ],
  "limit": 20,
  "page": 0,
  "totalCount": 1,
  "totalPages": 1
}

Schritt 2 – Datei hochladen

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project/{projectId}/data-bucket/{dataBucketId}/upload \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -F "file=@/pfad/zur/datei"
import { postProjectDataBucketUpload } from '@vcsuite/publisher-sdk';

const file = new File(['content'], 'filename.txt', { type: 'text/plain' });
const formData = new FormData();
formData.append('file', file);

await postProjectDataBucketUpload({ projectId, dataBucketId }, formData);

Hängen Sie overwrite=true an, um eine vorhandene Datei mit demselben Namen zu überschreiben. Die Swagger UI bietet ein Datei-Upload-Feld, über das Benutzer zur Datei auf ihrem lokalen Computer navigieren können.

Ein erfolgreicher Einzeldatei-Upload gibt 204 zurück. Beim Hochladen mehrerer Dateien kann die API 207 Multi-Status zurückgeben, wenn nur einige Dateien erfolgreich waren.

Teil B – Datenquelle erstellen

Eine Datenquelle ist eine registrierte Referenz auf Daten, die in einem Data Bucket oder unter einer externen URL gespeichert sind.

Es gibt zwei Quelltypen: internal (Data Bucket) und external (URL).

Interne Datenquelle:

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project/{projectId}/datasource \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Name der Datenquelle",
    "type": "geojson",
    "typeProperties": {
      "screenSpaceError": 16
    },
    "sourceProperties": {
      "type": "internal",
      "dataBucketId": "{dataBucketId}",
      "dataBucketKey": "pfad/zur/hochgeladenen/datei.json"
    }
  }'
import { postProjectDatasource } from '@vcsuite/publisher-sdk';

const datasource = await postProjectDatasource({ projectId }, {
  name: 'Name der Datenquelle',
  type: 'geojson',
  typeProperties: { screenSpaceError: 16 },
  sourceProperties: {
    type: 'internal',
    dataBucketId: dataBucketId,
    dataBucketKey: 'pfad/zur/hochgeladenen/datei.json'
  }
});

Externe Datenquelle:

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project/{projectId}/datasource \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Name der Datenquelle",
    "type": "wms",
    "typeProperties": {
      "layers": ["layer_name"],
      "version": "1.3.0",
      "format": "image/png"
    },
    "sourceProperties": {
      "type": "external",
      "url": "https://example.com/wms"
    }
  }'
import { postProjectDatasource } from '@vcsuite/publisher-sdk';

const datasource = await postProjectDatasource({ projectId }, {
  name: 'Name der Datenquelle',
  type: 'wms',
  typeProperties: {
    layers: ['layer_name'],
    version: '1.3.0',
    format: 'image/png'
  },
  sourceProperties: {
    type: 'external',
    url: 'https://example.com/wms'
  }
});

Die folgenden type-Werte werden unterstützt:

Typ Beschreibung

tileset

3D-Kachelset (z. B. Cesium 3D Tiles)

geojson

GeoJSON-Vektordaten

oblique

Schrägluftbilder

qmesh

Quantized-Mesh-Gelände

meshinmesh

Geländenetz im Netz

wms

Web Map Service

wmts

Web Map Tile Service

tms

Tile Map Service

cog

Cloud Optimized GeoTIFF

flatgeobuf

FlatGeobuf-Vektordaten

i3s

I3S Scene Layer

vectortiles

Vektorkacheln

generic

Generischer / benutzerdefinierter Typ

panorama

Panoramabilder

Eine erfolgreiche Antwort gibt 201 Created zurück:

{
  "_id": "ds-id-xyz...",
  "name": "Name der Datenquelle",
  "type": "geojson",
  "uri": "https://publisher-url.de/data/...",
  "projectId": "proj-id-abc123",
  "jobIds": [],
  "publishTaskIds": [],
  "dataUpdatedAt": "2026-03-11T09:30:00.000Z",
  "dataUpdatedBy": "user-id"
}

Schritt 5 – Alle Datenquellen auflisten

  • SHELL

  • JavaScript

curl https://{publisherUrl}/api/v1/project/{projectId}/datasources \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."
import { getProjectDatasources } from '@vcsuite/publisher-sdk';

const datasources = await getProjectDatasources({ projectId });

Workflow 6: App mit Modulen erstellen

Schritt 1 – App erstellen

Um eine App zu erstellen, senden Sie eine POST-Anfrage an /api/v1/project/{projectId}/app mit dem App-Namen, einer Beschreibung und einem Array von Modul-IDs. Das Feld mapVersion gibt die VC Map Viewer Engine-Version als Semver-Bereich an. Zusätzlich kann eine MemberId als Query-String hinzugefügt werden. Wenn keine MemberId angegeben wird, wird die App mit den Berechtigungen des anfragenden Benutzers erstellt. Wenn eine MemberId angegeben wird, wird die App mit den Berechtigungen dieses Benutzers erstellt. Die MemberId muss dem Projekt bereits zugewiesen sein.

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project/{projectId}/app \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Meine Stadt-App",
    "description": "Öffentlich zugängliche 3D-Stadt-App",
    "mapVersion": "^6.0.0",
    "moduleIds": ["module-id-abc"]
  }'
import { postProjectApp } from '@vcsuite/publisher-sdk';

const response = await postProjectApp({ projectId }, {
  name: 'Meine Stadt-App',
  description: 'Öffentlich zugängliche 3D-Stadt-App',
  mapVersion: '^6.0.0',
  moduleIds: ['module-id-abc']
});

Wenn mehrere Module in moduleIds aufgeführt sind, werden deren Layer und Viewpoints sequenziell zusammengeführt. Die Erstellung eines Moduls wird im nächsten Schritt beschrieben, aber Module können auch unabhängig erstellt und später zur App hinzugefügt werden.

Eine erfolgreiche Antwort gibt 201 Created zurück:

{
  "_id": "app-id-xyz",
  "name": "Meine Stadt-App",
  "projectId": "proj-id-abc123",
  "moduleIds": ["module-id-abc"],
  "mapVersion": "^6.0.0",
  "publishTaskIds": [],
  "isPublic": false,
  "createdAt": "2026-03-13T10:47:45.931Z",
  "updatedAt": "2026-03-13T10:47:45.931Z",
  "createdBy": "v6WEM2A92ozfZaAu5",
  "updatedBy": "v6WEM2A92ozfZaAu5"
}

Speichern Sie die _id als {appId}. Die App ist erst öffentlich zugänglich, nachdem sie in Schritt 6 veröffentlicht wurde.

Schritt 2 – Modul erstellen

  • SHELL

  • JavaScript

curl -X POST https://{publisherUrl}/api/v1/project/{projectId}/module \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mein Basismodul",
    "description": "Beschreibung meines Basismoduls",
    "properties": {},
    "layers": [
      {
        "type": "OpenStreetMapLayer",
        "name": "OpenStreetMapLayer(1)",
        "properties": {
          "attributions": {
            "provider": "OpenStreetMap contributors",
            "url": "http://www.openstreetmap.org/",
            "year": "2026"
          }
        },
        "activeOnStartup": true,
        "zIndex": 0
      },
      {
        "type": "GeoJSONLayer",
        "name": "test_api_datasource",
        "activeOnStartup": true,
        "url": "./datasource-data/f4a59d97-4401-45ab-b31a-2e5ad6569fc9/testLake3_withZ.json",
        "extent": {
          "coordinates": [12.278030916360558, 53.76142514632812, 12.32886225819537, 53.778920631506764],
          "projection": { "type": "Projection", "epsg": "EPSG:4326" },
          "type": "Extent"
        },
        "datasourceId": "f4a59d97-4401-45ab-b31a-2e5ad6569fc9",
        "zIndex": 0
      }
    ],
    "maps": [{ "type": "CesiumMap", "name": "CesiumMap" }],
    "contentTree": [
      {
        "type": "LayerContentTreeItem",
        "name": "OpenStreetMapLayer(1)",
        "layerName": "OpenStreetMapLayer(1)"
      }
    ],
    "startingMapName": "CesiumMap"
  }'
import { postProjectModule } from '@vcsuite/publisher-sdk';

const response = await postProjectModule({ projectId }, {
  name: 'Mein Basismodul',
  description: 'Beschreibung meines Basismoduls',
  properties: {},
  layers: [
    {
      type: 'OpenStreetMapLayer',
      name: 'OpenStreetMapLayer(1)',
      properties: {
        attributions: {
          provider: 'OpenStreetMap contributors',
          url: 'http://www.openstreetmap.org/',
          year: '2026'
        }
      },
      activeOnStartup: true,
      zIndex: 0
    },
    {
      type: 'GeoJSONLayer',
      name: 'test_api_datasource',
      activeOnStartup: true,
      url: './datasource-data/f4a59d97-4401-45ab-b31a-2e5ad6569fc9/testLake3_withZ.json',
      extent: {
        coordinates: [12.278030916360558, 53.76142514632812, 12.32886225819537, 53.778920631506764],
        projection: { type: 'Projection', epsg: 'EPSG:4326' },
        type: 'Extent'
      },
      datasourceId: 'f4a59d97-4401-45ab-b31a-2e5ad6569fc9',
      zIndex: 0
    }
  ],
  maps: [{ type: 'CesiumMap', name: 'CesiumMap' }],
  contentTree: [{ type: 'LayerContentTreeItem', name: 'OpenStreetMapLayer(1)', layerName: 'OpenStreetMapLayer(1)' }],
  startingMapName: 'CesiumMap'
});

Die Layer im Modul können auf Datenquellen referenzieren, die in Workflow 5 erstellt wurden. Eine erfolgreiche Antwort gibt 201 Created zurück:

{
  "_id": "module-id-abc",
  "name": "Mein Basismodul",
  "projectId": "proj-id-abc123",
  "layers": [ ... ],
  "viewpoints": [ ... ],
  "createdAt": "2026-03-11T09:45:00.000Z"
}

Schritt 3 – Module hinzufügen

Dies ersetzt das bestehende moduleIds-Array vollständig – fügen Sie alle Module ein, nicht nur die neuen: Es müssen nur die Felder in den Anfrage-Body aufgenommen werden, die überschrieben werden sollen.

  • SHELL

  • JavaScript

curl -X PUT https://{publisherUrl}/api/v1/project/{projectId}/app/{appId} \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..." \
  -H "Content-Type: application/json" \
  -d '{
    "moduleIds": ["module-id-abc", "module-id-second"]
  }'
import { putProjectApp } from '@vcsuite/publisher-sdk';

await putProjectApp({ projectId, appId }, {
  moduleIds: ['module-id-abc', 'module-id-second']
});