Entwickler-Schnittstelle · Version 1
Termine-API
Alle Konzerttermine von adventskonzerte-berlin.de als JSON – für Kalender, Gemeindeseiten, Apps und Bildschirme im Foyer.
- Kostenlos
- Ohne Anmeldung und ohne API-Schlüssel
- Nur lesen
- CORS offen
- OpenAPI 3.1
Schnellstart
Basis-URL: https://api.adventskonzerte-berlin.de. Alle Antworten sind JSON in UTF-8; Fehler ebenfalls.
curl https://api.adventskonzerte-berlin.de/v1/termine
Bitte höchstens einmal pro Stunde abfragen. Die Termine ändern sich nur selten. Zwischenspeichern Sie die Antwort und nutzen Sie ETag und If-None-Match.
Endpunkte
Erlaubt sind GET, HEAD und OPTIONS.
GET/v1/termine
Alle veröffentlichten Termine, sortiert nach beginn, bei Gleichstand nach reihenfolge. Optional gefiltert.
{
"termine": [
"… Termin-Objekte …"
],
"anzahl": 1,
"stand": "2026-11-09T10:15:00.000Z",
"quelle": "https://adventskonzerte-berlin.de/konzerte/"
}
anzahl ist die Zahl der gelieferten Termine, stand der Zeitpunkt, zu dem die Website die Daten erzeugt hat, quelle die Seite mit den Terminen.
GET/v1/termine/{id}
Ein einzelnes Termin-Objekt, z. B. /v1/termine/friedrichshain. Unbekannte Kennung → 404.
{
"id": "friedrichshain",
"name": "Friedrichshain",
"reihenfolge": 3,
"datum": "2026-12-19",
"uhrzeit": "17:30",
"beginn": "2026-12-19T17:30:00+01:00",
"zeitzone": "Europe/Berlin",
"veranstalter": "Eckstein-Gemeinde",
"adresse": "An der Schillingbrücke 4, 10243 Berlin",
"website": {
"url": "https://eckstein.online",
"text": "eckstein.online"
},
"bild": {
"url": "https://adventskonzerte-berlin.de/bilder/konzerte_05.webp",
"beschreibung": "Konzert Friedrichshain"
},
"koordinaten": {
"breitengrad": 52.509829,
"laengengrad": 13.429333
},
"livestream": false,
"links": {
"konzertseite": "https://adventskonzerte-berlin.de/konzerte/#termine",
"karte": "https://www.google.com/maps/search/?api=1&query=Eckstein-Gemeinde%2C%20An%20der%20Schillingbr%C3%BCcke%204%2C%2010243%20Berlin"
}
}
Weitere Adressen
GET /v1– kleine Übersicht mit LinksGET /gesundheit– antwortet{"status": "ok"}(zählt zum Rate Limit)GET /openapi.json– maschinenlesbare Spezifikation (OpenAPI 3.1)GET /bzw./doku/– diese Seite
Filter
Für /v1/termine, beliebig kombinierbar. Leere Ergebnisse liefern anzahl: 0, keinen Fehler.
| Parameter | Wert | Bedeutung |
|---|---|---|
ab | YYYY-MM-DD | Termine an oder nach diesem Tag (einschließlich). |
bis | YYYY-MM-DD | Termine an oder vor diesem Tag (einschließlich). |
livestream | true | false | Nur Termine mit bzw. ohne Livestream. |
Ungültige Werte führen zu 400 mit Code ungueltiger_parameter.
https://api.adventskonzerte-berlin.de/v1/termine?ab=2026-12-01&bis=2026-12-24&livestream=true
Feldverzeichnis: Termin-Objekt
Alle Felder sind immer vorhanden. Nur website kann null sein. Versteckte Termine werden nicht ausgegeben.
| Feld | Typ | Beschreibung |
|---|---|---|
id | string | Eindeutige, stabile Kennung (Dateiname, z. B. friedrichshain). Für /v1/termine/{id}. |
name | string | Name des Termins, meist der Bezirk. |
reihenfolge | integer | Redaktionelle Reihenfolge; zweites Sortierkriterium nach beginn. |
datum | string (date) | Konzerttag im Format YYYY-MM-DD. |
uhrzeit | string | Beginn als Berliner Ortszeit, HH:MM. |
beginn | string (date-time) | Beginn als ISO 8601 mit Zeitversatz, z. B. 2026-12-19T17:30:00+01:00. Sommer- und Winterzeit sind berücksichtigt. |
zeitzone | string | Immer Europe/Berlin. |
veranstalter | string | Gemeinde oder Veranstalter. |
adresse | string | Anschrift des Veranstaltungsorts. |
website | object | null | Website des Veranstalters, sonst null. |
website.url | string (uri) | Adresse der Website. |
website.text | string | Anzeigetext für den Link. |
bild | object | Bild zum Termin. |
bild.url | string (uri) | Absolute Bildadresse (WebP). |
bild.beschreibung | string | Alternativtext – bitte als alt verwenden. |
koordinaten | object | Lage des Veranstaltungsorts (WGS 84). |
koordinaten.breitengrad | number | Breitengrad, z. B. 52.509829. |
koordinaten.laengengrad | number | Längengrad, z. B. 13.429333. |
livestream | boolean | true, wenn das Konzert live übertragen wird. |
links | object | Weiterführende Links. |
links.konzertseite | string (uri) | Konzertseite der Website (Abschnitt mit allen Terminen). |
links.karte | string (uri) | Ort in der Karten-App (Google-Maps-Link, öffnet auf dem Handy die Karten-App). |
Tipp: Für Kalender und Zeitberechnungen beginn verwenden – das Feld enthält den korrekten Zeitversatz. datum und uhrzeit eignen sich für die Anzeige.
Rate Limits
Damit der kostenlose Dienst für alle verfügbar bleibt, gelten pro IP-Adresse feste Grenzen. Jede Anfrage zählt – auch 304-Antworten, HEAD und /gesundheit. Nur CORS-Vorabanfragen (OPTIONS) zählen nicht.
- 5 Anfragen pro Minute
- 30 Anfragen pro Stunde
- 100 Anfragen pro Tag
Empfehlung: höchstens einmal pro Stunde abfragen, das Ergebnis zwischenspeichern und mit If-None-Match nachfragen. Für Webseiten mit vielen Besuchern: die Daten auf Ihrem Server abrufen und von dort ausliefern, statt jeden Browser direkt anfragen zu lassen.
Antwort-Header
| Header | Beispiel | Bedeutung |
|---|---|---|
X-RateLimit-Limit | 30 | Erlaubte Anfragen im Stundenfenster. |
X-RateLimit-Remaining | 27 | Verbleibende Anfragen im Stundenfenster. |
X-RateLimit-Reset | 1834 | Sekunden bis zum Zurücksetzen des Stundenfensters. |
RateLimit-Policy | "minute";q=5;w=60, "stunde";q=30;w=3600, "tag";q=100;w=86400 | Geltende Grenzen nach IETF-Entwurf. |
RateLimit | "stunde";r=27;t=1834 | Aktueller Stand nach IETF-Entwurf. |
Retry-After | 60 | Nur bei 429: Sekunden bis zur nächsten erlaubten Anfrage. |
Bei 429 Too Many Requests: nicht sofort wiederholen. Warten Sie mindestens die in Retry-After angegebenen Sekunden. Wiederholte Anfragen während der Sperre verlängern nichts, werden aber ebenfalls abgewiesen.
{
"fehler": {
"code": "zu_viele_anfragen",
"nachricht": "Zu viele Anfragen. Bitte in 1834 Sekunden erneut versuchen."
}
}
Caching & ETag
Antworten tragen Cache-Control: public, max-age=900 (15 Minuten) und einen ETag. Schicken Sie den ETag beim nächsten Abruf als If-None-Match mit: Hat sich nichts geändert, antwortet die API mit 304 Not Modified ohne Inhalt – schnell und sparsam. Auch 304-Antworten zählen zum Rate Limit; der Vorteil liegt in der geringeren Datenmenge.
Die API liest ihre Daten selbst aus der Website, mit etwa 15 Minuten Zwischenspeicher. Änderungen erscheinen daher mit kurzer Verzögerung. Der Zeitpunkt der Datenerzeugung steht in stand.
Fehlercodes
Fehler kommen immer als JSON in dieser Form:
{ "fehler": { "code": "nicht_gefunden", "nachricht": "Termin „mitte“ nicht gefunden." } }
Werten Sie code aus – nachricht ist für Menschen gedacht und kann sich ändern.
| HTTP | code | Bedeutung |
|---|---|---|
400 | ungueltiger_parameter | Filterwert ungültig, z. B. ab=19.12.2026 statt 2026-12-19. |
404 | nicht_gefunden | Termin oder Adresse existiert nicht. |
405 | methode_nicht_erlaubt | Andere Methode als GET, HEAD oder OPTIONS. |
429 | zu_viele_anfragen | Rate Limit überschritten. Retry-After abwarten. |
503 | quelle_nicht_erreichbar | Die Datenquelle ist vorübergehend nicht erreichbar. Später erneut versuchen. |
503 | konfiguration_fehlt | Die API ist auf Betreiberseite nicht vollständig eingerichtet. Später erneut versuchen. |
Beispiele
curl
# Alle Termine
curl -i https://api.adventskonzerte-berlin.de/v1/termine
# Nur Termine im Dezember mit Livestream
curl "https://api.adventskonzerte-berlin.de/v1/termine?ab=2026-12-01&bis=2026-12-31&livestream=true"
# Ein einzelner Termin
curl https://api.adventskonzerte-berlin.de/v1/termine/friedrichshain
# Bedingte Anfrage: 304, wenn sich nichts geändert hat
curl -i -H 'If-None-Match: "a1b2c3d4"' https://api.adventskonzerte-berlin.de/v1/termine
JavaScript (fetch)
// Funktioniert im Browser (CORS ist offen) und in Node.js ab Version 18.
const antwort = await fetch('https://api.adventskonzerte-berlin.de/v1/termine?ab=2026-12-01');
if (antwort.status === 429) {
const warten = Number(antwort.headers.get('Retry-After') ?? 60);
throw new Error('Rate Limit erreicht, bitte in ' + warten + ' s erneut versuchen.');
}
if (!antwort.ok) {
const { fehler } = await antwort.json();
throw new Error(fehler.code + ': ' + fehler.nachricht);
}
const { termine, stand } = await antwort.json();
for (const t of termine) {
const zeit = new Date(t.beginn).toLocaleString('de-DE', {
dateStyle: 'full', timeStyle: 'short', timeZone: t.zeitzone,
});
console.log(zeit, '–', t.name, '–', t.adresse);
}
console.log('Datenstand:', stand);
Python
# Nur Standardbibliothek, Python 3.8+
import json, time, urllib.request, urllib.error
URL = "https://api.adventskonzerte-berlin.de/v1/termine"
etag, termine = None, []
def abrufen():
global etag, termine
anfrage = urllib.request.Request(URL, headers={"User-Agent": "mein-kalender/1.0"})
if etag:
anfrage.add_header("If-None-Match", etag)
try:
with urllib.request.urlopen(anfrage, timeout=10) as antwort:
etag = antwort.headers.get("ETag")
termine = json.load(antwort)["termine"]
except urllib.error.HTTPError as e:
if e.code == 304:
return termine # unverändert, alten Stand behalten
if e.code == 429:
time.sleep(int(e.headers.get("Retry-After", "60")))
raise
return termine
for t in abrufen():
print(t["datum"], t["uhrzeit"], t["name"], "Livestream" if t["livestream"] else "")
CORS
Die API sendet Access-Control-Allow-Origin: *. Sie kann also direkt aus jeder Webseite per fetch abgefragt werden, ohne Cookies oder Anmeldedaten. Vorabanfragen (OPTIONS) werden beantwortet und zählen nicht zum Rate Limit. Bedenken Sie bei direkter Einbindung, dass jeder Besucher Ihrer Seite eigene Anfragen erzeugt – und die Grenzen pro Besucher-IP gelten.
Datenschutz
Für die Rate Limits wird jede IP-Adresse nur als gesalzener Hash (SHA-256 mit täglich wechselndem Salz) gezählt. Die Zählerstände werden spätestens nach 24 Stunden gelöscht. Es werden keine Zugriffsprotokolle mit IP-Adressen geführt, keine Cookies gesetzt und keine Daten an Dritte weitergegeben. Die API wird über Cloudflare betrieben. Weitere Informationen in der Datenschutzerklärung.
Kontakt & Nutzung
Die Termindaten dürfen gern übernommen werden. Bitte nennen Sie als Quelle adventskonzerte-berlin.de und verlinken Sie auf die Konzertseite (links.konzertseite). Fragen und Hinweise: siehe Impressum.