-
Notifications
You must be signed in to change notification settings - Fork 0
API Reference
THD Room Finder communicates with THabella, THD's public scheduling system. All endpoints are unauthenticated and use POST requests.
Disclaimer: THabella has no official public API documentation. These endpoints were reverse-engineered from THabella's frontend RequireJS source code (
/js/src/functions.js,/js/src/drag.js,/js/src/board.js,/js/src/gui.js). They could change without notice.
https://thabella.th-deg.de/thabella/opn/
No authentication required. No known rate limits (but the app implements caching to be respectful).
Fetches all rooms in the THabella system.
Request:
POST /thabella/opn/room/findRooms HTTP/1.1
Host: thabella.th-deg.de
Content-Type: application/json
{}The request body is an empty JSON object.
Response: 200 OK — JSON array of room objects.
[
{
"id": 42,
"ident": "I112",
"name": "I 112",
"seatsRegular": 60,
"seatsExam": 40,
"facilities": "Beamer, Whiteboard",
"bookable": true,
"inCharge": {
"id": 1,
"uid": "jdoe",
"firstname": "John",
"lastname": "Doe",
"email": "john.doe@th-deg.de",
"phone": null
},
"collisions": null,
"reservations": null,
"state": null,
"accessNames": null
}
]Response fields:
| Field | Type | Notes |
|---|---|---|
id |
Int |
Primary key |
ident |
String |
Room identifier without spaces (e.g., "I112") |
name |
String |
Display name with spaces (e.g., "I 112") |
seatsRegular |
Int? |
Regular seating capacity |
seatsExam |
Int? |
Exam seating capacity |
facilities |
String? |
Comma-separated list (e.g., "Beamer, Whiteboard") |
bookable |
Boolean? |
Whether the room can be reserved |
inCharge |
Object? |
Person responsible for the room |
inCharge.firstname |
String? |
First name |
inCharge.lastname |
String? |
Last name |
inCharge.email |
String? |
Contact email |
collisions, reservations, state, accessNames
|
Various | Always null in public API |
Current count: 289 rooms.
Fetches scheduled events (lectures, exams, etc.) for a specific date.
Request:
POST /thabella/opn/period/findByDate/2025-02-10%2008:00 HTTP/1.1
Host: thabella.th-deg.de
Content-Type: application/json
{"sqlDate": "2025-02-10 08:00"}The {dateTime} path parameter format is yyyy-MM-dd HH:mm (URL-encoded space → %20).
The request body repeats the date in sqlDate field.
Response: 200 OK — JSON array of period objects.
[
{
"id": 12345,
"startDateTime": "2025-02-10 08:00",
"duration": 90,
"room_ident": {
"42": "I 112"
},
"eventTypeDescription": "Vorlesung",
"titleText": null,
"eventId": null,
"description": null,
"organiser": null,
"participants": null
}
]Response fields:
| Field | Type | Notes |
|---|---|---|
id |
Int |
Period ID |
startDateTime |
String |
"yyyy-MM-dd HH:mm" format |
duration |
Int |
Duration in minutes |
room_ident |
Map<String, String> |
Room ID → display name. Not an array! One event can span multiple rooms. |
eventTypeDescription |
String? |
Type of event (e.g., "Vorlesung", "Prüfung") |
titleText |
String? |
Event title — always null in public API |
eventId |
Int? |
Always null in public API |
description |
String? |
Always null in public API |
organiser |
Object? |
Always null in public API |
participants |
Array? |
Always null in public API |
The room_ident field is Map<String, String> where:
-
Key = room ID (as string, e.g.,
"42") -
Value = room display name (e.g.,
"I 112")
A single event can occupy multiple rooms. The app maps one PeriodDto to N ScheduledEvent domain objects — one per room in the map.
The app uses kotlinx.serialization with these safety settings:
Json {
ignoreUnknownKeys = true // API may add new fields
isLenient = true // Handles minor format issues
coerceInputValues = true // Null → default for non-nullable fields
}All DTO fields are nullable with sensible defaults. If parsing fails for a single period, that period is skipped rather than crashing the entire response.
To minimize load on THabella:
| Data | Cache TTL | Strategy |
|---|---|---|
| Rooms | 24 hours | Room list rarely changes |
| Events | 5 minutes | Schedules can change throughout the day |
Cache is stored in a local Room database and used as fallback when the network is unavailable.