Datensatz hochladen per API¶
Dieser Guide beschreibt, wie eine CSV-Datei samt Metadaten über die ODI-API hochgeladen wird. Der Ablauf gliedert sich in drei Phasen: Schema-ID ermitteln → Metadaten-IDs ermitteln → Token abrufen → CSV hochladen. Datei und Metadaten werden dabei in einem einzigen HTTP-Multipart-Request übergeben.
Das Backend validiert die hochgeladene CSV-Datei automatisch gegen das angegebene Schema. Nur bei erfolgreicher Validierung wird der Datensatz angelegt.
Test-System verfügbar
Für die Entwicklung und Tests steht ein Staging-System bereit. Die Zugangsdaten (Keycloak-URL, Realm, Client-Credentials) sind auf Anfrage erhältlich. Bitte wende dich dazu an das ODI-Team.
Voraussetzungen¶
- Client-ID und Client-Secret eines Keycloak Service Accounts liegen vor (Admins: siehe Programmatischen API-Zugriff einrichten)
- CSV-Datei ist lokal vorhanden, Encoding und Delimiter sind bekannt
- Schema-ID und Schema-Version des passenden Schemas sind bekannt (siehe Schema-ID ermitteln)
- Folgende Metadaten-IDs sind bekannt (siehe Metadaten-IDs abrufen):
- Katalog-Name (
catalogue), z. B.opendata-sh - Lizenz-ID (
licenseId), z. B.http://dcat-ap.de/def/licenses/cc-zero - Publisher-ID (
publisherId), z. B.dataport - Kategorie-IDs (
categoryIdsJsonString), z. B.["envi"] - Raumbezug-ID (
spatialReferenceId), z. B.http://dcat-ap.de/def/politicalGeocoding/stateKey/01
- Katalog-Name (
Schema-ID ermitteln¶
Das Schema definiert die erwartete Struktur der hochzuladenden CSV-Datei.
schemaId und schemaVersion sind Pflichtfelder im Upload-Request.
Das Schema-Repository ist unter schema.odi.schleswig-holstein.de/schemas erreichbar. Dort sind alle verfügbaren Schemas mit ihren IDs und Versionen aufgelistet. Die Schema-ID und die Schemaversion befindet sich auf der Schema-Detailseite.
Vorgehen:
- Schema-Repository öffnen.
- Passendes Schema identifizieren.
- Schema-ID (z. B.
8569) und Version (z. B.1.3.1) notieren.
Tip
Die verfügbaren Schemas können auch über die Schema-Repository API abgerufen werden.
Metadaten-IDs abrufen¶
Mehrere Pflichtfelder des Upload-Requests referenzieren Objekte, die im Metadaten-Service verwaltet werden. Eine Übersicht aller verfügbaren IDs und Endpunkte ist unter Metadaten-IDs abrufen zu finden.
Häufig verwendete Werte:
| Feld | Wert | Kommentar |
|---|---|---|
catalogue |
opendata-sh |
|
licenseId |
http://dcat-ap.de/def/licenses/cc-zero |
Creative Commons CC Zero |
licenseId |
http://dcat-ap.de/def/licenses/dl-zero-de/2.0 |
Datenlizenz Deutschland Zero 2.0 |
licenseId |
http://dcat-ap.de/def/licenses/officialWork |
Amtliches Werk |
spatialReferenceId |
http://dcat-ap.de/def/politicalGeocoding/stateKey/01 |
Bundesland Schleswig-Holstein |
categoryIdsJsonString |
["envi"] |
Umwelt |
categoryIdsJsonString |
["tran"] |
Verkehr |
categoryIdsJsonString |
["gove"] |
Regierung und öffentlicher Sektor |
Token abrufen (Keycloak Service Account)¶
Alle schreibenden API-Requests erfordern ein gültiges JWT-Token für diesen ein Service-Account notwendig ist.
Tip
Der Service-Account wird vom Administrator angelegt. Eine ausführliche Anleitung zur Einrichtung findet sich unter Programmatischen API-Zugriff einrichten.
Die Zugangsdaten bestehen aus einer Client-ID und einem Client-Secret.
Request:
curl -X POST \
"https://keycloak.odi.schleswig-holstein.de/realms/open-data-infrastruktur/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<client-id>" \
-d "client_secret=<client-secret>"
Beispiel-Response:
{
"access_token": "eyJ...",
"expires_in": 300,
"token_type": "Bearer"
}
Den Wert von access_token im nächsten Schritt als Bearer-Token verwenden. Dies ist nötig um Daten über die API hochzuladen.
Warning
Client-Secrets niemals in Versionsverwaltungssystemen oder Logs speichern.
Tokens sind zeitlich begrenzt gültig (expires_in Sekunden); nach Ablauf muss ein neuer Token angefordert werden.
CSV-Datei hochladen¶
Zum Hochladen einer CSV-Datei genügt ein einziger Request.
Beim Hochladen wird die CSV-Datei automatisch gegen das angegebene Schema validiert. Im Fehlerfall wird ein Validierungsbericht im frictionless-Report-Format zurückgeliefert – ein Beispiel der Fehlerreports befindet sich weiter unten.
Nach dem erfolgreichen Hochladen wird der Datensatz im Datenkatalog angelegt. Dabei werden folgende Dateien automatisch erzeugt:
- Die hochgeladene CSV-Datei
- Eine Tabular Data Resource-Datei
- Eine Apache Parquet-Datei
Enthält das Schema Geo-Informationen, werden zusätzlich angelegt:
- GeoJSON-Datei
- GeoParquet-Datei
- WFS-Service
- WMS-Service
- Kartenansicht (Link zum Masterportal)
Request¶
POST "https://staging-backend.odi.schleswig-holstein.de/upload/csv"
Felder (Request Body)¶
| Feld | Pflicht | Typ | Beschreibung | Quelle |
|---|---|---|---|---|
catalogue |
Pflicht | string | Katalog, in dem der Datensatz gespeichert wird | Metadaten-Service /catalogs |
title |
Pflicht | JSON-Objekt | Titel des Datensatzes (mehrsprachig) | frei wählbar |
description |
Pflicht | JSON-Objekt | Beschreibung (mehrsprachig) | frei wählbar |
schemaId |
Pflicht | string | ID des Schemas im Schema-Repository | Schema-Repository |
schemaVersion |
Pflicht | string | Version des Schemas | Schema-Repository |
delimiter |
Pflicht | string | Trennzeichen der CSV-Datei (z. B. ; oder ,) |
bekannt aus Datei |
encoding |
Pflicht | string | Zeichenkodierung (z. B. UTF-8) |
bekannt aus Datei |
quote |
Pflicht | string | Anführungszeichen-Zeichen (z. B. ") |
bekannt aus Datei |
file |
Pflicht | binary | Die CSV-Datei | lokal |
startDate |
Pflicht | string | Startdatum des Datensatz-Zeitraums im ISO-8601-Format (z. B. 2024-01-01) |
bekannt |
endDate |
Optional | string | Enddatum des Datensatz-Zeitraums im ISO-8601-Format (z. B. 2024-12-31) |
– |
licenseId |
Pflicht | string | ID der Lizenz | Metadaten-Service /licenses |
datasetId |
Pflicht | string | Frei wählbare ID des Datensatzes | frei wählbar |
publisherId |
Pflicht | string | ID des Herausgebers | Metadaten-Service /publisher |
categoryIdsJsonString |
Pflicht | string (JSON) | JSON-Array der Kategorie-IDs als String | Metadaten-Service /categories |
spatialReferenceId |
Pflicht | string | ID des Raumbezugs | Metadaten-Service /places |
draft |
Pflicht | string | "true" = Draft anlegen; "false" = veröffentlichen |
– |
Info
title und description sind mehrsprachige JSON-Objekte, z. B.:
{"de": "Windkraftanlagen", "en": "Wind turbines"}
Sie werden als JSON-String im multipart-Body übergeben.
Beispiel-Request (Windkraftanlagen)¶
Der access_token wird im Abschnitt Token abrufen ermittelt.
curl --request POST \
--url https://staging-backend.odi.schleswig-holstein.de/upload/csv \
--header 'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...' \ # <access_token> aus dem vorherigen Schritt
--header 'content-type: multipart/form-data' \
--form catalogue=opendata-sh \
--form 'title={"de":"Windkraftanlagen"}' \
--form 'description={"de":"Dieser Datensatz enthält Daten und Standorte von genehmigungspflichtigen Windkraftanlagen in Schleswig-Holstein."}' \
--form schemaId=7269 \
--form schemaVersion=1.2.2 \
--form 'delimiter=;' \
--form encoding=UTF-8 \
--form 'quote="' \
--form file=@/pfad/zur/windkraftanlagen.csv \
--form startDate=2026-01-01 \
--form licenseId=http://dcat-ap.de/def/licenses/cc-zero \
--form datasetId=windkraftanlagen-2026 \
--form publisherId=dataport \
--form 'categoryIdsJsonString=["ener", "envi"]' \
--form spatialReferenceId=http://dcat-ap.de/def/politicalGeocoding/stateKey/01 \
--form draft=false
Beispiel-Response (Erfolg)¶
{
"datasetId": "windkraftanlagen-2026",
"datasetUrl": "https://opendata.schleswig-holstein.de/dataset/windkraftanlagen-2026"
}
Beispiel-Response (Fehlerfall - Validierung fehlgeschlagen)¶
{
"status": "error",
"type": "invalid file",
"message": "Validation of Csv-File was not valid!",
"context": "CsvUploadService",
"errors": [
{
"description": "The cell \"Harburg\" in row at position \"2\" and field \"KREIS\" at position \"1\" does not conform to a constraint: constraint \"enum\" is \"['Dithmarschen', 'Kiel', 'Lübeck', 'Nordfriesland', 'Hzgt.Lauenburg', 'Ostholstein', 'Plön', 'Pinneberg', 'Rendsburg-Eckernförde', 'Segeberg', 'Schleswig-Flensburg', 'Steinburg', 'Stormarn']\"",
"index": 2,
"field": "KREIS"
}
]
}
Fehlercodes¶
| HTTP-Status | Bedeutung | Mögliche Ursache / Lösung |
|---|---|---|
| 400 | Ungültige Anfrage | Pflichtfeld fehlt, falsches Format oder CSV entspricht nicht dem Schema |
| 401 | Nicht authentifiziert | Token fehlt oder abgelaufen → neuen Token abrufen |
| 403 | Keine Berechtigung | Service Account hat nicht die erforderliche Rolle |
| 413 | Datei zu groß | Datei übersteigt das serverseitige Größenlimit |
| 500 | Interner Serverfehler | Kontakt zum ODI-Support aufnehmen |
Beispiel-Response (403 – Keine Berechtigung): Tritt auf, wenn der Service Account keine Schreibrechte für den angegebenen Publisher hat oder keine Berechtigung für den Upload eingerichtet wurde.
{
"status": "error",
"type": "forbidden",
"message": "CsvUploadService"
}
Als Draft speichern (optional)¶
Optional: Als Draft speichern
Durch Setzen von draft=true im Upload-Request wird der Datensatz zunächst als Entwurf angelegt
und ist öffentlich noch nicht sichtbar. Dies empfiehlt sich, wenn der Datensatz vor der
Veröffentlichung noch manuell geprüft werden soll.
Nächste Schritte¶
- Datensatz aktualisieren per API – eine neue Version einer bestehenden CSV hochladen (
PUT /upload/csv/overwrite/{datasetId})