Skip to main content

Asset Manager API

Einleitung

Das Asset Manager API ist ein schreibgeschütztes HTTP-API zum Lesen von Daten aus einem SQL Server.

Es handelt sich nicht um ein klassisches REST-API.

Bei einem klassischen REST-API sind die Datenstrukturen normalerweise fest bekannt. Es gibt zum Beispiel feste Endpunkte wie:

GET /api/customers
GET /api/orders
GET /api/products

Das API kennt dabei die Tabellen, Spalten und Datenmodelle bereits zur Entwicklungszeit.

Bei diesem API ist das anders. Die Datenbank des Asset Managers wird kundenseitig dynamisch definiert. Das bedeutet:

  • Es ist vorher nicht bekannt, welche Tabellen existieren.
  • Es ist vorher nicht bekannt, welche Views existieren.
  • Es ist vorher nicht bekannt, welche Spalten eine Tabelle oder View hat.
  • Das API kann deshalb keine festen Endpunkte pro Datenobjekt anbieten.

Darum muss zuerst abgefragt werden, welche Tabellen oder Views vorhanden sind. Danach werden die Spalten dieser Objekte ermittelt. Erst mit diesem Wissen können gezielt Daten gelesen werden.

Der typische Ablauf ist:

1. Optional Verfügbarkeit prüfen: /health oder /ready
2. Verfügbare Tabellen oder Views abrufen
3. Spalten einer Tabelle oder View abrufen
4. Optional Anzahl der Datensätze abrufen
5. Daten mit Spaltenauswahl, Sortierung, Paging und Filtern lesen

Grundprinzip

Das API liest Metadaten aus SQL Server und verwendet diese Informationen zur Validierung.

Alle übergebenen Namen werden gegen SQL-Server-Metadaten geprüft:

  • Schema
  • Tabelle
  • View
  • Spalten
  • Sortierspalten
  • Filterspalten
  • Cursor-Spalten für after

Rohe SQL-Fragmente werden nicht akzeptiert.

Dadurch kann das API dynamisch arbeiten, ohne beliebige SQL-Befehle von außen auszuführen. SQL-Bezeichner werden nach der Validierung intern sicher maskiert.


Authentifizierung

Das API verwendet einen API-Key im HTTP-Header.

Der Headername ist:

X-API-Key: <your-api-key>

Alle geschützten Endpunkte benötigen diesen Header.

Ausnahmen:

Route API-Key erforderlich Grund
/health Nein Liveness-Prüfung
/ready Nein Readiness-Prüfung
/swagger Nein Swagger UI, wenn aktiviert
/swagger-ui/* Nein Swagger UI Assets, wenn aktiviert

/openapi.json ist nicht ausgenommen. Dieser Endpunkt benötigt einen API-Key.

Fehlt der API-Key oder ist er falsch, antwortet das API mit:

401 Unauthorized
{
  "Error": "Invalid or missing API key."
}

Betrieb und Konfiguration

Folgende Konfigurationsbereiche sind für das API relevant:

Bereich Wert Bedeutung
ServiceOptions:SqlServer Pflicht SQL-Server-Name oder Adresse. Fehlt der Wert, startet das API nicht.
ServiceOptions:SqlDatabase Pflicht SQL-Datenbank. Fehlt der Wert, startet das API nicht.
ServiceOptions:SqlUsername Optional SQL-Anmeldename.
ServiceOptions:SqlPassword Optional SQL-Passwort. Wenn gesetzt, wird versucht, den Wert zu entschlüsseln.
ServiceOptions:SqlPort Optional Bei 0 oder kleiner wird der Default aus ServiceOptions verwendet.
ServiceOptions:SqlTimeout Optional Bei 0 oder kleiner wird der Default aus ServiceOptions verwendet.
ServiceOptions:ApiKey Pflicht für geschützte Endpunkte API-Key für Requests. /ready meldet, ob er konfiguriert ist.
ServiceOptions:ApiName Optional Name für /api/help, Swagger und Health-Antworten.
ServiceOptions:ApiVersion Optional Version für /api/help, Swagger und Health-Antworten.
Swagger:Enabled Optional Aktiviert /swagger und /openapi.json.
RateLimit:PermitLimit Optional, Default 60 Anzahl erlaubter Requests pro Fenster und Remote-IP. Muss größer als 0 sein.
RateLimit:WindowSeconds Optional, Default 60 Länge des Rate-Limit-Fensters in Sekunden. Muss größer als 0 sein.
RateLimit:QueueLimit Optional, Default 0 Warteschlangenlimit. Muss 0 oder größer sein.

Das API erzwingt HTTPS-Weiterleitung.


Rate-Limit

Das API verwendet ein globales Fixed-Window-Rate-Limit.

Standardwerte:

Einstellung Standard
PermitLimit 60
WindowSeconds 60
QueueLimit 0

Der Rate-Limit-Bucket wird anhand der Remote-IP gebildet. Wenn keine Remote-IP verfügbar ist, wird der Bucket unknown verwendet.

Wenn das Rate-Limit greift, antwortet das API mit:

429 Too Many Requests
{
  "Error": "Too many requests."
}

Falls verfügbar, wird zusätzlich der Header Retry-After gesetzt.

Das Rate-Limit gilt global und damit auch für Health-, Ready-, Swagger- und API-Key-fehlgeschlagene Requests.


Einschränkungen

Das API ist absichtlich eingeschränkt:

Einschränkung Bedeutung
Nur lesender Zugriff Es gibt keine Endpunkte zum Erstellen, Ändern oder Löschen von Daten.
take muss zwischen 1 und 1000 liegen Pro Anfrage können maximal 1000 Zeilen gelesen werden.
Standard für take in /api/data Die implementierte Abfragelogik verwendet 100, wenn take fehlt.
skip muss 0 oder größer sein Negative Werte sind nicht erlaubt.
skip > 0 benötigt Sortierung Erlaubt ist orderBy oder sort im Format Column:direction.
after benötigt Sortierung Erlaubt ist orderBy oder sort im Format Column:direction.
after und skip dürfen nicht kombiniert werden Offset-Paging und Keyset-Paging sind getrennte Modi.
Keine rohen SQL-Fragmente SQL-Teile wie WHERE 1=1 oder DROP TABLE werden nicht als Parameter akzeptiert.
Tabellen- und View-Listen sind eingeschränkt /api/tables und /api/views listen nur Objekte im Schema dbo, keine Systemobjekte und keine Namen, die mit __ beginnen.
Objektzugriff ist eingeschränkt /api/columns, /api/count und /api/data akzeptieren nur User-Tabellen und Views, keine Systemobjekte und keine Namen, die mit __ beginnen.

Endpunkte

Methode Pfad API-Key Zweck
GET /health Nein Prüft, ob das API lebt.
GET /ready Nein Prüft Konfiguration und Datenbankverbindung.
GET /swagger Nein Swagger UI, wenn aktiviert.
GET /openapi.json Ja OpenAPI-Spezifikation, wenn Swagger aktiviert ist.
GET /api/help Ja Kompakte JSON-Hilfe zum API.
GET /api/views Ja Gibt verfügbare SQL-Server-Views zurück.
GET /api/tables Ja Gibt verfügbare SQL-Server-Tabellen zurück.
GET /api/columns Ja Gibt Spaltenmetadaten einer Tabelle oder View zurück.
GET /api/count Ja Gibt die Anzahl der Datensätze einer Tabelle oder View zurück.
GET /api/data Ja Streamt Datenzeilen als JSON.

GET /health

Prüft, ob das API erreichbar ist.

Dieser Endpunkt benötigt keinen API-Key.

Parameter

Keine

Beispiel

GET /health

Beispielantwort

{
  "status": "healthy",
  "version": "1.0.0",
  "timeUtc": "2026-06-25T10:00:00Z"
}

Verwendung

Dieser Endpunkt ist für Liveness-Checks gedacht. Er prüft nicht, ob die Datenbank erreichbar ist.


GET /ready

Prüft, ob das API betriebsbereit ist.

Dieser Endpunkt benötigt keinen API-Key.

Geprüft werden:

  • ServiceOptions:SqlServer
  • ServiceOptions:SqlDatabase
  • ServiceOptions:ApiKey
  • Datenbankverbindung per SELECT 1

Parameter

Keine

Beispiel

GET /ready

Erfolgreiche Beispielantwort

200 OK
{
  "status": "ready",
  "database": "ok",
  "version": "1.0.0",
  "timeUtc": "2026-06-25T10:00:00Z"
}

Fehlerhafte Beispielantwort

503 Service Unavailable
{
  "status": "not_ready",
  "configuration": "ok",
  "apiKey": "missing",
  "database": "error",
  "error": "Login failed for user ...",
  "version": "1.0.0",
  "timeUtc": "2026-06-25T10:00:00Z"
}

Verwendung

Dieser Endpunkt ist für Readiness-Checks gedacht. Er zeigt, ob das API vollständig konfiguriert ist und die Datenbank erreicht.


GET /openapi.json

Gibt die OpenAPI-Spezifikation im JSON-Format zurück.

Dieser Endpunkt ist nur vorhanden, wenn Swagger:Enabled aktiv ist.

Dieser Endpunkt benötigt einen API-Key.

Parameter

Keine

Beispiel

GET /openapi.json
X-API-Key: <your-api-key>

Antwort

Die Antwort ist ein OpenAPI-v3-Dokument mit API-Key-Security-Schema.


GET /swagger

Gibt die Swagger UI zurück.

Dieser Endpunkt ist nur vorhanden, wenn Swagger:Enabled aktiv ist.

Die UI selbst benötigt keinen API-Key. API-Aufrufe aus der UI sowie der Abruf von /openapi.json benötigen trotzdem den Header X-API-Key.

Parameter

Keine

Beispiel

GET /swagger

GET /api/help

Gibt eine kompakte JSON-Hilfe zum API zurück.

Dieser Endpunkt benötigt einen API-Key.

Parameter

Keine

Beispiel

GET /api/help
X-API-Key: <your-api-key>

Zweck

Dieser Endpunkt zeigt:

  • Name des API
  • Beschreibung
  • Authentifizierung
  • Einschränkungen
  • verfügbare Routen
  • Beispielparameter
  • Beispielantworten
  • erlaubte Filteroperatoren
  • Beispiele für Sortierung, Filter und Keyset-Paging

GET /api/views

Gibt verfügbare SQL-Server-Views zurück.

Parameter

Keine

Beispiel

GET /api/views
X-API-Key: <your-api-key>

Beispielantwort

[
  {
    "Schema": "dbo",
    "Name": "CustomerOverview"
  },
  {
    "Schema": "dbo",
    "Name": "OpenOrders"
  }
]

Einschränkung

Dieser Endpunkt listet aktuell nur Views:

  • im Schema dbo
  • ohne is_ms_shipped
  • deren Name nicht mit __ beginnt

Eine View kann anschließend wie eine Tabelle über /api/columns, /api/count und /api/data verwendet werden.


GET /api/tables

Gibt verfügbare SQL-Server-Tabellen zurück.

Parameter

Keine

Beispiel

GET /api/tables
X-API-Key: <your-api-key>

Beispielantwort

[
  {
    "Schema": "dbo",
    "Name": "Customers"
  },
  {
    "Schema": "dbo",
    "Name": "Orders"
  }
]

Einschränkung

Dieser Endpunkt listet aktuell nur Tabellen:

  • im Schema dbo
  • ohne is_ms_shipped
  • deren Name nicht mit __ beginnt

GET /api/columns

Gibt Spaltenmetadaten einer ausgewählten Tabelle oder View zurück.

Parameter

Parameter Pflicht Beschreibung
schema Ja Name des SQL-Schemas, zum Beispiel dbo.
table Ja Name der SQL-Tabelle oder View, zum Beispiel Customers oder CustomerOverview.

Beispiel

GET /api/columns?schema=dbo&table=Customers
X-API-Key: <your-api-key>

Beispielantwort

[
  {
    "Name": "Id",
    "StoreType": "int",
    "Nullable": false,
    "Ordinal": 1,
    "MaxLength": 4,
    "Precision": 10,
    "Scale": 0,
    "IsIdentity": true,
    "IsComputed": false,
    "IsPrimaryKey": true,
    "IsForeignKey": false,
    "ReferencedSchema": null,
    "ReferencedTable": null,
    "ReferencedColumn": null,
    "Description": "Primärschlüssel"
  },
  {
    "Name": "CustomerId",
    "StoreType": "int",
    "Nullable": false,
    "Ordinal": 2,
    "MaxLength": 4,
    "Precision": 10,
    "Scale": 0,
    "IsIdentity": false,
    "IsComputed": false,
    "IsPrimaryKey": false,
    "IsForeignKey": true,
    "ReferencedSchema": "dbo",
    "ReferencedTable": "Customers",
    "ReferencedColumn": "Id",
    "Description": null
  }
]

Felder der Antwort

Feld Bedeutung
Name Name der Spalte.
StoreType SQL-Datentyp der Spalte.
Nullable Gibt an, ob die Spalte NULL enthalten darf.
Ordinal Position der Spalte in der Tabelle oder View.
MaxLength SQL-Server-max_length. Bei nvarchar und nchar ist das die Byte-Länge. -1 bedeutet max.
Precision SQL-Server-Precision. Relevant bei numerischen Typen und bestimmten Zeittypen.
Scale SQL-Server-Scale. Relevant bei numerischen Typen und bestimmten Zeittypen.
IsIdentity Gibt an, ob die Spalte eine Identity-Spalte ist.
IsComputed Gibt an, ob die Spalte berechnet ist.
IsPrimaryKey Gibt an, ob die Spalte Teil eines Primary Keys ist.
IsForeignKey Gibt an, ob die Spalte Teil eines Foreign Keys ist.
ReferencedSchema Ziel-Schema des Foreign Keys oder null.
ReferencedTable Ziel-Tabelle des Foreign Keys oder null.
ReferencedColumn Ziel-Spalte des Foreign Keys oder null.
Description Wert aus MS_Description oder null.

Fehlerantwort

Wenn die Tabelle oder View nicht existiert oder keine Berechtigung besteht:

404 Not Found
{
  "Error": "Table or view was not found or no permission exists."
}

Verwendung

Dieser Endpunkt wird vor /api/data verwendet.

So wird ermittelt, welche Spalten über columns, orderBy, sort, after oder filters verwendet werden können.


GET /api/count

Gibt die Anzahl der Datensätze einer Tabelle oder View zurück.

Intern wird COUNT_BIG(*) verwendet. Das Ergebnis kann größer als ein 32-Bit-Integer sein.

Parameter

Parameter Pflicht Beschreibung
Schema Ja Name des SQL-Schemas, zum Beispiel dbo.
Table Ja Name der SQL-Tabelle oder View, zum Beispiel Customers oder CustomerOverview.

Beispiel

GET /api/count?Schema=dbo&Table=Customers
X-API-Key: <your-api-key>

Beispielantwort

{
  "Schema": "dbo",
  "Table": "Customers",
  "Count": 42
}

Fehlerantworten

Wenn Schema oder Table fehlt:

400 Bad Request
{
  "Error": "Schema and Table are required."
}

Wenn die Tabelle oder View nicht existiert oder keine Berechtigung besteht:

404 Not Found
{
  "Error": "Table or view was not found or no permission exists."
}

Verwendung

Dieser Endpunkt ist nützlich für:

  • Anzeige der Gesamtanzahl
  • Vorbereitung von Paging
  • Prüfung, ob eine Tabelle oder View Daten enthält

GET /api/data

Gibt Zeilen einer Tabelle oder View als gestreamtes JSON zurück.

Dieser Endpunkt ist der zentrale Datenlese-Endpunkt.

Vor der Abfrage werden validiert:

  • Schema
  • Tabelle oder View
  • ausgewählte Spalten
  • Sortierspalten
  • Cursor-Spalten für after
  • Filterspalten
  • Filteroperatoren
  • Filterwerte anhand des SQL-Spaltentyps

Parameter

Parameter Pflicht Standard Beschreibung
schema Ja - Name des SQL-Schemas, zum Beispiel dbo.
table Ja - Name der Tabelle oder View, zum Beispiel Customers.
columns Nein * Kommaseparierte Spaltenliste. Mit * oder ohne Parameter werden alle Spalten zurückgegeben.
orderBy Nein - Kompatibilitätsformat für Sortierung. Spalte oder kommaseparierte Spaltenliste, zum Beispiel orderBy=manufacturer,product,version. Kann mit sort=asc oder sort=desc kombiniert werden.
sort Nein asc bei orderBy Entweder globale Richtung asc oder desc zusammen mit orderBy, oder bevorzugtes Format pro Spalte: Column:asc,OtherColumn:desc.
take Nein 100 Maximale Anzahl der Zeilen. Erlaubt sind Werte von 1 bis 1000.
skip Nein 0 Anzahl der zu überspringenden Zeilen. Bei Werten größer als 0 ist orderBy oder per-column sort erforderlich.
after Nein - Keyset-Cursor für Folgeseiten. Benötigt orderBy oder per-column sort. Bei mehreren Sortierspalten werden die Werte mit \| getrennt. Nicht mit skip kombinieren.
filters Nein - Kommaseparierte Filter im Format Spalte:Operator:Wert. Mehrere Filter werden mit AND verknüpft. Mehrfachwerte für in, nin und between werden mit \| getrennt.

Beispielantwort

[
  {
    "Id": 1,
    "Name": "Mueller"
  },
  {
    "Id": 2,
    "Name": "Schmidt"
  }
]

Spaltenauswahl

Alle Spalten lesen

GET /api/data?schema=dbo&table=Customers&columns=*
X-API-Key: <your-api-key>

Der Parameter columns=* bedeutet: alle Spalten zurückgeben.

Der Parameter kann auch weggelassen werden. Dann werden ebenfalls alle Spalten zurückgegeben.

Bestimmte Spalten lesen

GET /api/data?schema=dbo&table=Customers&columns=Id,Name
X-API-Key: <your-api-key>

In diesem Beispiel werden nur die Spalten Id und Name gelesen.

Die Spaltennamen müssen in der Tabelle oder View existieren.

Doppelte Spalten in columns werden ignoriert. Die erste Schreibweise aus den SQL-Metadaten wird verwendet.


Sortierung

Keine Sortierung

GET /api/data?schema=dbo&table=Customers&take=100
X-API-Key: <your-api-key>

Ohne Sortierung verwendet das API intern SELECT TOP (@take). Die Reihenfolge ist dann nicht stabil und nicht für Paging geeignet.

Einfache Sortierung

GET /api/data?schema=dbo&table=Customers&orderBy=Id
X-API-Key: <your-api-key>

Standardmäßig wird aufsteigend sortiert.

Das entspricht:

GET /api/data?schema=dbo&table=Customers&orderBy=Id&sort=asc
X-API-Key: <your-api-key>

Absteigende Sortierung

GET /api/data?schema=dbo&table=Customers&orderBy=Id&sort=desc
X-API-Key: <your-api-key>

Sortierung nach mehreren Spalten mit globaler Richtung

GET /api/data?schema=dbo&table=Customers&orderBy=manufacturer,product,version&sort=asc
X-API-Key: <your-api-key>

Die Sortierspalten werden in der angegebenen Reihenfolge verwendet. Die globale Richtung gilt für alle Sortierspalten.

Sortierung nach mehreren Spalten mit Richtung pro Spalte

GET /api/data?schema=dbo&table=Assets&sort=Manufacturer:asc,Product:asc,Version:desc&take=100
X-API-Key: <your-api-key>

Dieses Format ist das bevorzugte neue Sortierformat.

Regeln:

  • sort=Column:asc,OtherColumn:desc darf nicht mit orderBy kombiniert werden.
  • Wenn orderBy fehlt, muss sort das Format Column:direction verwenden.
  • Wenn orderBy gesetzt ist, darf sort nur asc oder desc enthalten.
  • Erlaubte Richtungen sind asc und desc.
  • Sortierspalten müssen in der Tabelle oder View existieren.

Paging

Paging bedeutet: Daten werden seitenweise gelesen.

Es gibt zwei Paging-Arten:

Art Parameter Verwendung
Offset-Paging take, skip, orderBy oder per-column sort Einfach, aber bei großen Offsets weniger performant.
Keyset-Paging take, after, orderBy oder per-column sort Performanter für Folgeseiten, benötigt Cursor-Werte aus der letzten Zeile der vorherigen Seite.

Offset-Paging

Erste Seite

GET /api/data?schema=dbo&table=Customers&orderBy=Id&take=100&skip=0
X-API-Key: <your-api-key>

Bedeutung:

  • Maximal 100 Zeilen lesen.
  • Keine Zeilen überspringen.
  • Nach Id sortieren.

Zweite Seite

GET /api/data?schema=dbo&table=Customers&orderBy=Id&take=100&skip=100
X-API-Key: <your-api-key>

Bedeutung:

  • Die ersten 100 Zeilen überspringen.
  • Danach maximal 100 Zeilen lesen.

Wichtige Regel

Sobald skip größer als 0 ist, muss orderBy oder per-column sort angegeben werden.

Grund: Ohne feste Sortierung kann SQL Server die Reihenfolge der Zeilen ändern. Dann wäre Paging nicht stabil.


Keyset-Paging mit after

after ist ein Cursor für Folgeseiten.

Der Cursor enthält die Werte der Sortierspalten aus der letzten Zeile der vorherigen Seite.

Erste Seite lesen

GET /api/data?schema=dbo&table=Assets&orderBy=Id&take=100
X-API-Key: <your-api-key>

Wenn die letzte Zeile der Antwort zum Beispiel Id = 12345 hat, wird die nächste Seite so gelesen:

GET /api/data?schema=dbo&table=Assets&orderBy=Id&after=12345&take=100
X-API-Key: <your-api-key>

Keyset-Paging mit mehreren Sortierspalten

GET /api/data?schema=dbo&table=Assets&sort=Manufacturer:asc,Product:asc,Id:asc&after=Microsoft|Office|12345&take=100
X-API-Key: <your-api-key>

Bedeutung:

Manufacturer > Microsoft
OR Manufacturer = Microsoft AND Product > Office
OR Manufacturer = Microsoft AND Product = Office AND Id > 12345

Bei absteigender Sortierung wird der Vergleich umgedreht.

Regeln für after

  • after benötigt orderBy oder per-column sort.
  • after darf nicht mit skip kombiniert werden, wenn skip > 0 ist.
  • after muss genau einen Wert pro Sortierspalte enthalten.
  • Mehrere Cursor-Werte werden mit | getrennt.
  • Die Cursor-Werte werden anhand der jeweiligen SQL-Spaltentypen konvertiert.
  • Bei strikter URL-Kodierung kann | als %7C gesendet werden.

Filter

Filter werden über den Parameter filters angegeben.

Format:

Spalte:Operator:Wert

Mehrere Filter werden mit Komma getrennt:

Spalte1:Operator:Wert,Spalte2:Operator:Wert

Mehrere Filter werden mit AND verbunden.

Beispiel

GET /api/data?schema=dbo&table=Orders&columns=OrderId&filters=Status:eq:Open,Amount:gt:100&orderBy=OrderId
X-API-Key: <your-api-key>

Bedeutung:

Status = Open
AND Amount > 100

Es wird nur die Spalte OrderId zurückgegeben.


Erlaubte Filteroperatoren

Operator SQL-Vergleich Wert erforderlich Bedeutung
eq = Ja Gleich
ne <> Ja Ungleich
gt > Ja Größer als
gte >= Ja Größer oder gleich
lt < Ja Kleiner als
lte <= Ja Kleiner oder gleich
like LIKE Ja SQL-LIKE-Vergleich. % muss URL-kodiert werden.
in IN Ja Wert ist in einer \|-getrennten Liste enthalten.
nin NOT IN Ja Wert ist nicht in einer \|-getrennten Liste enthalten.
isnull IS NULL Nein Wert ist NULL.
notnull IS NOT NULL Nein Wert ist nicht NULL.
between BETWEEN Ja, zwei Werte Wert liegt zwischen zwei \|-getrennten Grenzen.
startswith LIKE Ja Beginnt mit dem angegebenen Wert. Das API hängt % intern an.
endswith LIKE Ja Endet mit dem angegebenen Wert. Das API stellt % intern voran.
contains LIKE Ja Enthält den angegebenen Wert. Das API setzt % intern vor und hinter den Wert.

Beispiele für Filter

Gleichheit

GET /api/data?schema=dbo&table=Orders&filters=Status:eq:Open&orderBy=OrderId
X-API-Key: <your-api-key>

Größer als

GET /api/data?schema=dbo&table=Orders&filters=Amount:gt:100&orderBy=OrderId
X-API-Key: <your-api-key>

LIKE-Suche

GET /api/data?schema=dbo&table=Customers&filters=Name:like:M%25&orderBy=Name&sort=asc&take=50
X-API-Key: <your-api-key>

%25 ist die URL-kodierte Form von %.

Der Filter entspricht sinngemäß:

Name LIKE 'M%'

Startswith

GET /api/data?schema=dbo&table=Customers&filters=Name:startswith:M&orderBy=Name&take=50
X-API-Key: <your-api-key>

Entspricht sinngemäß:

Name LIKE 'M%'

Endswith

GET /api/data?schema=dbo&table=Customers&filters=Name:endswith:son&orderBy=Name&take=50
X-API-Key: <your-api-key>

Entspricht sinngemäß:

Name LIKE '%son'

Contains

GET /api/data?schema=dbo&table=Customers&filters=Name:contains:soft&orderBy=Name&take=50
X-API-Key: <your-api-key>

Entspricht sinngemäß:

Name LIKE '%soft%'

IN

GET /api/data?schema=dbo&table=Assets&filters=Status:in:Open|Pending|Failed&orderBy=Id
X-API-Key: <your-api-key>

Entspricht sinngemäß:

Status IN ('Open', 'Pending', 'Failed')

NOT IN

GET /api/data?schema=dbo&table=Assets&filters=Status:nin:Closed|Deleted&orderBy=Id
X-API-Key: <your-api-key>

IS NULL

GET /api/data?schema=dbo&table=Assets&filters=DeletedAt:isnull:&orderBy=Id
X-API-Key: <your-api-key>

Der Wertteil muss leer bleiben.

IS NOT NULL

GET /api/data?schema=dbo&table=Assets&filters=DeletedAt:notnull:&orderBy=Id
X-API-Key: <your-api-key>

Der Wertteil muss leer bleiben.

BETWEEN

GET /api/data?schema=dbo&table=Assets&filters=CreatedAt:between:2024-01-01|2024-12-31&orderBy=CreatedAt
X-API-Key: <your-api-key>

Entspricht sinngemäß:

CreatedAt BETWEEN '2024-01-01' AND '2024-12-31'

Typisierte Filterwerte

Filterwerte werden nicht als roher SQL-Text eingesetzt. Das API erzeugt SQL-Parameter und konvertiert den Wert anhand des SQL-Spaltentyps.

Beispiele:

SQL-Typ Erwartetes Wertformat
int, bigint, smallint, tinyint Ganzzahl, zum Beispiel 123.
decimal, numeric, money, smallmoney Dezimalzahl mit invariantem Format, zum Beispiel 123.45.
float, real Fließkommazahl mit invariantem Format.
bit true, false, 1 oder 0.
date, datetime, datetime2, smalldatetime Datumswert, sinnvollerweise ISO-Format wie 2024-12-31 oder 2024-12-31T10:30:00Z.
datetimeoffset Datumswert mit Offset, zum Beispiel 2024-12-31T10:30:00+01:00.
time Zeitspanne, zum Beispiel 12:30:00.
uniqueidentifier GUID, zum Beispiel 6f9619ff-8b86-d011-b42d-00cf4fc964ff.
binary, varbinary, image, rowversion, timestamp Hex mit 0x oder Base64.
Texttypen Rohwert als Text.

Wenn ein Wert nicht zum Spaltentyp passt, antwortet das API mit 400:

{
  "Error": "Invalid filter value for column 'Amount'. Expected SQL type decimal."
}

JSON-Ausgabe von /api/data

Die Daten werden als JSON-Array gestreamt.

SQL-/CLR-Wert JSON-Ausgabe
NULL null
Text JSON-String
Boolean JSON-Boolean
Zahlen JSON-Number
DateTime, DateTimeOffset JSON-String
Guid JSON-String
byte[] Base64-String
TimeSpan String im konstanten Format, zum Beispiel 01:30:00

Die Namen der JSON-Felder entsprechen den Spaltennamen aus SQL Server.


Beispielablauf

1. Betriebsbereitschaft prüfen

GET /ready

Beispielantwort:

{
  "status": "ready",
  "database": "ok",
  "version": "1.0.0",
  "timeUtc": "2026-06-25T10:00:00Z"
}

2. Tabellen abrufen

GET /api/tables
X-API-Key: <your-api-key>

Beispielantwort:

[
  {
    "Schema": "dbo",
    "Name": "Customers"
  }
]

Jetzt ist bekannt, dass es die Tabelle dbo.Customers gibt.


3. Spalten der Tabelle abrufen

GET /api/columns?schema=dbo&table=Customers
X-API-Key: <your-api-key>

Beispielantwort:

[
  {
    "Name": "Id",
    "StoreType": "int",
    "Nullable": false,
    "Ordinal": 1,
    "MaxLength": 4,
    "Precision": 10,
    "Scale": 0,
    "IsIdentity": true,
    "IsComputed": false,
    "IsPrimaryKey": true,
    "IsForeignKey": false,
    "ReferencedSchema": null,
    "ReferencedTable": null,
    "ReferencedColumn": null,
    "Description": "Primärschlüssel"
  },
  {
    "Name": "Name",
    "StoreType": "nvarchar",
    "Nullable": true,
    "Ordinal": 2,
    "MaxLength": 200,
    "Precision": 0,
    "Scale": 0,
    "IsIdentity": false,
    "IsComputed": false,
    "IsPrimaryKey": false,
    "IsForeignKey": false,
    "ReferencedSchema": null,
    "ReferencedTable": null,
    "ReferencedColumn": null,
    "Description": null
  }
]

Jetzt ist bekannt, dass die Spalten Id und Name verfügbar sind.


4. Anzahl der Datensätze abrufen

GET /api/count?Schema=dbo&Table=Customers
X-API-Key: <your-api-key>

Beispielantwort:

{
  "Schema": "dbo",
  "Table": "Customers",
  "Count": 42
}

5. Daten lesen

GET /api/data?schema=dbo&table=Customers&columns=Id,Name&orderBy=Id&take=100&skip=0
X-API-Key: <your-api-key>

Beispielantwort:

[
  {
    "Id": 1,
    "Name": "Mueller"
  },
  {
    "Id": 2,
    "Name": "Schmidt"
  }
]

6. Nächste Seite mit Keyset-Paging lesen

Wenn die letzte gelesene Zeile Id = 2 hat:

GET /api/data?schema=dbo&table=Customers&columns=Id,Name&orderBy=Id&after=2&take=100
X-API-Key: <your-api-key>

Weitere Beispiele für /api/data

Alle Spalten lesen

GET /api/data?schema=dbo&table=Customers&columns=*&orderBy=Id&take=100&skip=0
X-API-Key: <your-api-key>

Nur bestimmte Spalten lesen

GET /api/data?schema=dbo&table=Customers&columns=Id,Name&orderBy=Id&take=100&skip=0
X-API-Key: <your-api-key>

Nach mehreren Spalten sortieren

GET /api/data?schema=dbo&table=Customers&columns=*&orderBy=manufacturer,product,version&take=100&skip=0
X-API-Key: <your-api-key>

Nach mehreren Spalten mit eigener Richtung sortieren

GET /api/data?schema=dbo&table=Assets&sort=Manufacturer:asc,Product:asc,Version:desc&take=100
X-API-Key: <your-api-key>

Mit mehreren Filtern lesen

GET /api/data?schema=dbo&table=Orders&columns=OrderId&filters=Status:eq:Open,Amount:gt:100&orderBy=OrderId
X-API-Key: <your-api-key>

LIKE-Suche verwenden

GET /api/data?schema=dbo&table=Customers&filters=Name:like:M%25&orderBy=Name&sort=asc&take=50
X-API-Key: <your-api-key>

BETWEEN verwenden

GET /api/data?schema=dbo&table=Assets&filters=CreatedAt:between:2024-01-01|2024-12-31&orderBy=CreatedAt
X-API-Key: <your-api-key>

IN verwenden

GET /api/data?schema=dbo&table=Assets&filters=Status:in:Open|Pending|Failed&orderBy=Id
X-API-Key: <your-api-key>

IS NULL verwenden

GET /api/data?schema=dbo&table=Assets&filters=DeletedAt:isnull:&orderBy=Id
X-API-Key: <your-api-key>

Keyset-Paging mit einer Sortierspalte

GET /api/data?schema=dbo&table=Assets&orderBy=Id&after=12345&take=100
X-API-Key: <your-api-key>

Keyset-Paging mit mehreren Sortierspalten

GET /api/data?schema=dbo&table=Assets&sort=Manufacturer:asc,Product:asc,Id:asc&after=Microsoft|Office|12345&take=100
X-API-Key: <your-api-key>

Sicherheit und Validierung

Das API schützt sich dadurch, dass Eingaben nicht direkt als SQL übernommen werden.

Stattdessen wird geprüft, ob die angegebenen Objekte wirklich existieren:

Eingabe Prüfung
schema Muss als SQL-Schema für das angefragte Objekt existieren.
table Muss als User-Tabelle oder View existieren. Systemobjekte und Namen mit __ am Anfang werden abgelehnt.
columns Jede angeforderte Spalte muss existieren.
orderBy Jede Sortierspalte muss existieren.
sort Jede Sortierspalte muss existieren. Jede Richtung muss asc oder desc sein.
after Muss genau einen typisierbaren Wert pro Sortierspalte enthalten.
filters Jede Filterspalte muss existieren.
Filteroperator Muss einer der erlaubten Operatoren sein.
Filterwert Muss zum SQL-Spaltentyp passen.

Nicht erlaubt sind direkte SQL-Fragmente wie:

Id; DROP TABLE Customers
Name ASC; DELETE FROM Orders
1=1

Das API erwartet strukturierte Parameter, keine SQL-Befehle.


Fehlerantworten und Statuscodes

Statuscode Ursache Beispielantwort
400 Pflichtparameter fehlt, Parameter ungültig, Spalte unbekannt, Operator ungültig, Filterwert nicht typisierbar oder unbekannte Route. { "Error": "take must be between 1 and 1000." }
401 API-Key fehlt oder ist falsch. { "Error": "Invalid or missing API key." }
404 Tabelle oder View wurde nicht gefunden oder es gibt keine Berechtigung. { "Error": "Table or view was not found or no permission exists." }
429 Rate-Limit erreicht. { "Error": "Too many requests." }
500 Unbehandelter Fehler, zum Beispiel fehlende API-Key-Konfiguration bei geschütztem Endpunkt. { "Error": "..." }
503 /ready ist nicht bereit. { "status": "not_ready", ... }

Alle Fehlerantworten werden als JSON zurückgegeben.


Typische Fehlerquellen

Tabelle oder View nicht vorher geprüft

Falsch:

GET /api/data?schema=dbo&table=Irgendwas
X-API-Key: <your-api-key>

Richtig:

GET /api/tables
GET /api/views

Danach mit einem vorhandenen Objekt weiterarbeiten.


Spalte existiert nicht

Falsch:

GET /api/data?schema=dbo&table=Customers&columns=CustomerName
X-API-Key: <your-api-key>

Richtig:

GET /api/columns?schema=dbo&table=Customers
X-API-Key: <your-api-key>

Danach nur vorhandene Spalten verwenden.


Paging ohne Sortierung

Falsch:

GET /api/data?schema=dbo&table=Customers&take=100&skip=100
X-API-Key: <your-api-key>

Richtig:

GET /api/data?schema=dbo&table=Customers&orderBy=Id&take=100&skip=100
X-API-Key: <your-api-key>

Oder mit per-column sort:

GET /api/data?schema=dbo&table=Customers&sort=Id:asc&take=100&skip=100
X-API-Key: <your-api-key>

orderBy mit per-column sort kombiniert

Falsch:

GET /api/data?schema=dbo&table=Assets&orderBy=Id&sort=Manufacturer:asc
X-API-Key: <your-api-key>

Richtig:

GET /api/data?schema=dbo&table=Assets&sort=Manufacturer:asc
X-API-Key: <your-api-key>

Oder:

GET /api/data?schema=dbo&table=Assets&orderBy=Id&sort=asc
X-API-Key: <your-api-key>

after ohne Sortierung

Falsch:

GET /api/data?schema=dbo&table=Assets&after=12345&take=100
X-API-Key: <your-api-key>

Richtig:

GET /api/data?schema=dbo&table=Assets&orderBy=Id&after=12345&take=100
X-API-Key: <your-api-key>

after mit skip kombiniert

Falsch:

GET /api/data?schema=dbo&table=Assets&orderBy=Id&after=12345&skip=100&take=100
X-API-Key: <your-api-key>

Richtig:

GET /api/data?schema=dbo&table=Assets&orderBy=Id&after=12345&take=100
X-API-Key: <your-api-key>

Oder Offset-Paging ohne after:

GET /api/data?schema=dbo&table=Assets&orderBy=Id&skip=100&take=100
X-API-Key: <your-api-key>

Zu viele Zeilen angefordert

Falsch:

GET /api/data?schema=dbo&table=Customers&take=5000
X-API-Key: <your-api-key>

Richtig:

GET /api/data?schema=dbo&table=Customers&take=1000
X-API-Key: <your-api-key>

take darf maximal 1000 sein.


isnull oder notnull mit Wert verwendet

Falsch:

GET /api/data?schema=dbo&table=Assets&filters=DeletedAt:isnull:2024-01-01&orderBy=Id
X-API-Key: <your-api-key>

Richtig:

GET /api/data?schema=dbo&table=Assets&filters=DeletedAt:isnull:&orderBy=Id
X-API-Key: <your-api-key>

Filterwert passt nicht zum SQL-Typ

Falsch:

GET /api/data?schema=dbo&table=Orders&filters=Amount:gt:abc&orderBy=OrderId
X-API-Key: <your-api-key>

Richtig:

GET /api/data?schema=dbo&table=Orders&filters=Amount:gt:100.50&orderBy=OrderId
X-API-Key: <your-api-key>

Zusammenfassung

Das Asset Manager API dient zum sicheren, lesenden Zugriff auf dynamisch definierte SQL-Server-Tabellen und Views.

Der wichtigste Unterschied zu einem klassischen REST-API ist, dass die Datenstruktur nicht fest im Programm bekannt ist. Deshalb müssen Tabellen, Views und Spalten zuerst über Metadaten-Endpunkte abgefragt werden.

Empfohlener Ablauf:

/health oder /ready
/api/tables oder /api/views
/api/columns
/api/count
/api/data

Das API erlaubt nur lesende Zugriffe, validiert alle Objekt- und Spaltennamen gegen SQL-Server-Metadaten, typisiert Filterwerte und akzeptiert keine rohen SQL-Fragmente.