Zum Hauptinhalt springen

Datenschnittstelle

Über /data/<ns>/<api> wird auf die Datensätze der API api im Namensraum ns zugegriffen. Es gilt ein einfacher CRUD-Ansatz:

MethodeWirkung
POST /data/<ns>/<api>Legt einen Datensatz an. Er erhält eine vom Server vergebene Kennung (_id) und Meta-Daten (anlegendes Konto, Zeitpunkt).
PUT /data/<ns>/<api>[/<id>]Ändert einen Datensatz und aktualisiert die Meta-Daten (letztes Konto, Zeitpunkt). Übertragen werden nur die zu ändernden Felder. Substrukturen müssen immer vollständig übertragen werden.
DELETE /data/<ns>/<api>/<id>Löscht einen Datensatz.
GET /data/<ns>/<api>/<id>Liefert einen Datensatz.
GET /data/<ns>/<api>Liefert die erste Seite (100 Datensätze) aller Datensätze, im Format einer Abfrage.
POST /data/<ns>/<api>/queryErweiterte Suche mit Filter, Sortierung und Blättern, siehe Abfragen.

POST, PUT und DELETE antworten mit dem betroffenen Datensatz.

Bei PUT gibt es drei Möglichkeiten, die Kennung anzugeben:

  • nur in der URL (/data/<ns>/<api>/<id>), im Datensatz fehlt sie,
  • nur im Datensatz (_id), die URL ist /data/<ns>/<api>,
  • auf beiden Wegen, dann müssen beide identisch sein, sonst wird ein Fehler gemeldet.

Fehler meldet das CMS mit Status 400 und { "error": "<Meldung>" }, auch bei unbekannten Datensätzen. Fehlende Rechte meldet es mit 403.

Aufbau eines Datensatzes​

{
"_id": "894758ed-e701-4839-a085-3b77bb864d52",
"_cms": {
"created": "2026-10-21T09:12:44.123Z",
"createdBy": "<Kennung des Kontos>",
"lastModified": "2026-10-21T10:01:02.456Z",
"modifiedBy": "<Kennung des Kontos>"
},
"name": "Nicolas"
}

_cms wird vom CMS gepflegt und kann nicht gesetzt werden. _cms.lastModified eignet sich, um nur geänderte Datensätze abzurufen (siehe Abfragen).

Beispiele​

const cms = 'https://cms.example.org'
const headers = {
Authorization: 'Basic ' + btoa('CMS_User_01:<kennwort>'),
'Content-Type': 'application/json',
}
const people = `${cms}/data/tutorial/people`

async function call(url, options) {
const res = await fetch(url, { headers, ...options })
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`)
return res.json()
}

// Anlegen
const created = await call(people, { method: 'POST', body: JSON.stringify({ name: 'Nicolas', email: 'nicolas@example.org' }) })

// Einzeln lesen
const one = await call(`${people}/${created._id}`)

// Ändern: nur die geänderten Felder
await call(`${people}/${created._id}`, { method: 'PUT', body: JSON.stringify({ age: 43 }) })

// Suchen
const { items, filterCount } = await call(`${people}/query`, {
method: 'POST',
body: JSON.stringify({ filter: { age: { $gte: 18 } }, sort: { name: 'ascending' }, pageSize: 20 }),
})

// Löschen
await call(`${people}/${created._id}`, { method: 'DELETE' })

Dasselbe mit curl:

CMS=https://cms.example.org
USER='CMS_User_01:<kennwort>'

curl -X POST -u "$USER" -H 'Content-Type: application/json' -d '{ "name": "Nicolas", "email": "nicolas@example.org" }' "$CMS/data/tutorial/people"
curl -u "$USER" "$CMS/data/tutorial/people/<id>"
curl -X PUT -u "$USER" -H 'Content-Type: application/json' -d '{ "age": 43 }' "$CMS/data/tutorial/people/<id>"
curl -X POST -u "$USER" -H 'Content-Type: application/json' -d '{ "filter": { "age": { "$gte": 18 } } }' "$CMS/data/tutorial/people/query"
curl -X DELETE -u "$USER" "$CMS/data/tutorial/people/<id>"

Abruf für die Darstellung (?exported)​

Mit dem Parameter ?exported (bei GET und POST query) liefert das CMS die Datensätze in einer Form, die direkt angezeigt werden kann:

  • HTML-Felder enthalten fertiges HTML statt des internen draft-js-Formats.
  • In Dateifeldern (und ihren Vorschaubildern) enthält path die vollständige Abruf-URL (ohne Rechner und Port).
curl -u "$USER" "$CMS/data/tutorial/file/<id>?exported"

So abgerufene Datensätze sind nicht zum Zurückschreiben gedacht.

Dateien​

Abrufen​

Zum Abruf einer Datei braucht das Konto Leserecht auf die API, in deren Datensatz die Datei steht. Normal abgerufen sieht ein Dateifeld so aus:

{
"path": "ABCD",
"name": "myself.png",
"mime": "image/png",
"size": 1289173
}

path ist eine vom CMS vergebene, über alle Namensräume und APIs eindeutige Kennung. Der Inhalt liegt unter /media/<ns>/<api>/<path>, also analog zur Datenschnittstelle, nur mit media statt data und mit der Kennung der Datei statt der des Datensatzes: /media/tutorial/file/ABCD.

Mit ?exported steht die URL bereits im Feld:

{
"path": "/media/tutorial/file/ABCD",
"name": "myself.png",
"mime": "image/png",
"size": 1289173
}

/media unterstützt Teilabrufe (HTTP Range), wichtig für das Abspielen von Videos. Für die direkte Einbindung in <img> oder <video> hilft ein Kurzzeit-Token als Parameter ?token=….

Einspielen​

Datensätze mit Dateien werden als multipart/form-data übertragen. Das JSON des Datensatzes steht als Zeichenkette (JSON.stringify) im Formularwert data. Jedes Dateifeld enthält mindestens:

{
"path": "12345",
"name": "myself.png"
}

path ist hier der Name eines weiteren Formularwerts, der den Dateiinhalt enthält.

curl -X POST -u "$USER" \
-F 'data={ "title": "Ein erstes Bild", "image": { "path": "bild1", "name": "myself.png" } }' \
-F 'bild1=@myself.png' \
"$CMS/data/tutorial/file"
const form = new FormData()
form.append('data', JSON.stringify({ title: 'Ein erstes Bild', image: { path: 'bild1', name: 'myself.png' } }))
form.append('bild1', file) // z. B. aus einem <input type="file">

await fetch(`${cms}/data/tutorial/file`, {
method: 'POST',
headers: { Authorization: headers.Authorization }, // Content-Type setzt der Browser selbst
body: form,
})

Das gilt für POST und PUT gleichermaßen.