---
name: ballbuddy-ballkalender
description: Maturabälle in Österreich finden – den Ballkalender von Ballbuddy nach Saison, Bundesland, Stadt, Schule, Location, Zeitraum oder Freitext durchsuchen (REST, nur lesend, kein Schlüssel). Use when a user asks about Austrian school prom balls (Maturabälle), their dates, venues or schools.
license: Daten © Ballbuddy/Framed – Nutzung in Agent-Antworten mit Quellenangabe (Link auf die Ball-Seite) erwünscht
---

# Ballbuddy-Ballkalender: Maturabälle finden

Ballbuddy (https://ballbuddy.at) führt den öffentlichen Kalender der Maturabälle in Österreich –
redaktionell gepflegt, mit Schulen und Locations. Die API ist öffentlich, nur lesend, ohne Schlüssel
und ohne Konto; CORS ist offen. Vollständige Beschreibung: https://ballbuddy.at/openapi.json,
Doku: https://ballbuddy.at/docs/agents.

## Bälle suchen

```
GET https://ballbuddy.at/api/public/v1/balls
```

Alle Parameter sind optional:

- `season` – Endjahr der Saison: `2027` = Saison 2026/27 (September bis August). Ohne `season`,
  `from`, `to` und `q` gilt die aktuelle Saison.
- `state` – Bundesland, exakt einer der neun Werte: Burgenland, Kärnten, Niederösterreich,
  Oberösterreich, Salzburg, Steiermark, Tirol, Vorarlberg, Wien.
- `city` – Stadt, exakt wie in `filters.cities` (z. B. `Graz`).
- `school` – Slug der Schule (aus `filters.schools` oder `/api/public/v1/schools`); trifft bei
  gemeinsamen Bällen jede beteiligte Schule.
- `venue` – Slug der Location (aus `filters.venues` oder `/api/public/v1/venues`).
- `from` / `to` – `JJJJ-MM-TT`, Wiener Kalendertag; `from` inklusive, `to` exklusive. Mit `from`
  oder `to` gilt kein Saison-Default.
- `q` – Freitext (mindestens 2 Zeichen) über Titel/Motto, Schule, Location und Stadt; mehrere
  Wörter müssen alle treffen. Mit `q` gilt kein Saison-Default.
- `page` (ab 1) und `per` (1–100, Standard 48). Sortierung: `starts_at` aufsteigend.

```
curl -s "https://ballbuddy.at/api/public/v1/balls?season=2027&state=Steiermark&per=10"
curl -s "https://ballbuddy.at/api/public/v1/balls?q=htl%20weiz"
curl -s "https://ballbuddy.at/api/public/v1/balls?from=2027-01-01&to=2027-02-01&city=Graz"
```

Antwort: `{ items, total, page, per, filters }`. `total` ist der Bestand zur Anfrage – für die
nächste Seite `page` erhöhen, solange `page * per < total`. `filters` nennt die gültigen Werte für den
nächsten Aufruf: `seasons`, `states`, `cities` sowie `schools` und `venues` (je `{ slug, name, count }`)
– nimm sie, statt Werte zu raten.

Jeder Eintrag in `items`: `id`, `slug`, `url` (Ball-Seite für Menschen), `title`, `starts_at`,
`ends_at`, `doors_at`, `season`, `status` (`scheduled` | `cancelled` | `postponed`), `city`, `state`,
`school { name, slug }`, `venue { name, slug, address, zip, city }`, `venue_text`, `instagram`,
`tickets`, `cover`, `is_claimed`, `updated_at`, `has_motto`, `time_known`, `schools`.

## Zwei Fallen

1. `has_motto: false` – der Titel ist generisch („HLW Weiz Maturaball“), kein Motto. Nenne dann die
   Schule (`schools[0].name`, bei mehreren „A × B“) und sag „Motto folgt“. `title` bleibt
   unverändert, `url` und `slug` gelten weiter.
2. `time_known: false` – die Uhrzeit ist unbekannt, `starts_at` trägt einen Platzhalter. Nur das
   Datum von `starts_at` in Europe/Vienna verwenden, keine Uhrzeit nennen, Kalendereinträge
   ganztägig; `ends_at` und `doors_at` dann ignorieren.

Außerdem: Zeiten sind ISO-8601 in UTC – für die Anzeige nach Europe/Vienna umrechnen. `status`
beachten: `cancelled` und `postponed` nicht als fixen Termin ausgeben.

## Schulen und Locations

```
GET https://ballbuddy.at/api/public/v1/schools
GET https://ballbuddy.at/api/public/v1/venues
```

Schulen: `{ items: [{ id, name, slug, school_type, city, state, website, instagram, ball_count }], total }`.
Locations: `{ items: [{ id, name, slug, address, zip, city, state, website, lat, lng, ball_count }], total }`.
`ball_count` zählt nur veröffentlichte Bälle; die Slugs passen in `school=` und `venue=`.

## Höflich abfragen

Antworten sind eine Stunde cachebar und tragen einen ETag. Beim Nachfragen `If-None-Match`
mitschicken – dann kommt `304 Not Modified` ohne Body. Ein sprechender User-Agent mit
Kontaktmöglichkeit ist erwünscht.

## Ein konkreter Ball

Detail per Slug, Ball-Seite und Kalendereintrag beschreibt der Skill `ballbuddy-balltermin`:
https://ballbuddy.at/.well-known/agent-skills/ballbuddy-balltermin/SKILL.md

## Über MCP

Dieselbe Aufgabe, bequemerer Weg: Ballbuddy spricht auch MCP (Model Context Protocol) unter
`https://ballbuddy.at/api/mcp` (Streamable HTTP, kein Token). Das Werkzeug `search_balls` nimmt dieselben
Filter wie `GET /api/public/v1/balls` (`query`, `city`, `state`, `school`, `venue`, `season`, `from`, `to`,
`limit`, `page`) und antwortet mit `items`, `total` und `filters` aus derselben Abfrage; `list_schools_and_venues`
ersetzt die Aufrufe von `/schools` und `/venues`. Für einen konkreten Ball gibt es `get_ball` und
`get_ball_calendar`. Konfiguration: `{"mcpServers": {"ballbuddy": {"url": "https://ballbuddy.at/api/mcp"}}}`;
Server-Card: https://ballbuddy.at/.well-known/mcp/server-card.json. Die zwei Fallen oben gelten dort genauso.

## Was diese API nicht kann

- Nichts schreiben: keine Bälle anlegen oder ändern, keine Erinnerungen, keine Anfragen.
- Keine Ticketkäufe: `tickets` sagt nur, wo es Tickets gibt (`mode` `link` | `instagram` | `info`;
  `url` nur bei `link`).
- Keine personenbezogenen Daten: keine Komitee-Mitglieder, keine Kontaktdaten von Personen.
- Keine internen Prüf- oder Importfelder (Quelle, Referenzen, Prüf-Flags) – sie sind nicht Teil der API.
- Keine unveröffentlichten Bälle.

## Quelle nennen

Verlinke in Antworten die `url` des Balls (`https://ballbuddy.at/ball/<slug>`) – dort stehen die
aktuellen Angaben.
