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:SqlServerServiceOptions:SqlDatabaseServiceOptions: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:descdarf nicht mitorderBykombiniert werden.- Wenn
orderByfehlt, musssortdas FormatColumn:directionverwenden. - Wenn
orderBygesetzt ist, darfsortnurascoderdescenthalten. - Erlaubte Richtungen sind
ascunddesc. - 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
Idsortieren.
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
afterbenötigtorderByoder per-columnsort.afterdarf nicht mitskipkombiniert werden, wennskip > 0ist.aftermuss 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%7Cgesendet 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.