Konventionen
Jeder Endpunkt folgt denselben Konventionen für Statuscodes, Fehler, Wiederholungen und Paginierung. Einmal gelernt, gelten sie überall.
| Status | Bedeutung |
|---|---|
200 | Erfolg. |
201 | Eine Ressource wurde angelegt (ein Gast, ein Hold oder eine Gebühr). |
400 | Ungültige Anfrage: fehlerhaftes JSON oder ein Parameter, der die Validierung nicht bestanden hat. |
401 | Authentifizierung fehlgeschlagen: fehlender oder ungültiger API-Schlüssel. |
403 | Der Schlüssel ist gültig, hat aber nicht den nötigen Scope. |
404 | Die Route oder Ressource existiert nicht (oder gehört nicht Ihnen). |
405 | Der Pfad existiert, aber nicht für diese HTTP-Methode. |
409 | Konflikt: keine Verfügbarkeit, ein wiederverwendeter Idempotency-Key oder ein zu geringer Punktestand. |
429 | Rate Limit erreicht. Wiederholen Sie nach dem Retry-After-Header. |
500 | Interner Serverfehler. |
503 | Wartung. Die Plattform ist vorübergehend nicht verfügbar. Wiederholen Sie nach dem Retry-After-Header. |
Jeder Fehlschlag liefert den passenden Status und ein einzelnes error-Objekt:
{
"error": {
"type": "permission",
"code": "insufficient_scope",
"message": "Missing required scope: reservations:write.",
"request_id": "req_a1b2c3d4e5"
}
}type: die Kategorie:invalid_request,authentication,permission,not_found,conflict,rate_limitoderserver.code: eine stabile, maschinenlesbare Kennung. Verzweigen Sie hierauf, nicht aufmessage.message: eine für Menschen lesbare Erklärung. Zum Loggen geeignet, nicht zum Parsen.param: das Feld der Anfrage, das den Fehler ausgelöst hat. Nur bei Feldvalidierungsfehlern mit400vorhanden, sonst weggelassen.estimated_end: ein ISO-Zeitstempel für das voraussichtliche Ende eines Wartungsfensters. Nur bei503vorhanden und nur dann, wenn ein Endzeitpunkt gesetzt wurde. Er ist genauer als derRetry-After-Header, der daraus abgeleitet wird, nutzen Sie ihn also bevorzugt, wenn Sie einen Zustand „wieder verfügbar ab“ anzeigen.request_id: identifiziert die Anfrage eindeutig. Geben Sie sie an, wenn Sie den Support kontaktieren.
Code statt Meldung
Der Text von message kann sich ändern, code nicht. Verzweigen Sie Ihre Fehlerbehandlung über error.code (zum Beispiel no_availability, rate_plan_not_found, insufficient_points).
Häufige Codes, denen Sie begegnen werden:
| Code | Typ | Wann |
|---|---|---|
missing_api_key / invalid_api_key | authentication | Der Authorization-Header fehlt, oder der Schlüssel ist unbekannt, deaktiviert oder abgelaufen. |
insufficient_scope | permission | Dem Schlüssel fehlt der Scope des Endpunkts. |
invalid_parameters / invalid_json | invalid_request | Ein Feld hat die Validierung nicht bestanden, oder der Body war kein gültiges JSON. |
unknown_route | not_found | Kein Endpunkt passt zu diesem Pfad. |
no_availability | conflict | Der Zimmertyp ist für den angefragten Zeitraum ausgebucht. |
idempotency_key_reuse | conflict | Ein Idempotency-Key wurde mit einem anderen Anfrage-Body wiederverwendet. |
idempotency_in_progress | conflict | Eine frühere Anfrage mit demselben Idempotency-Key läuft noch. Wiederholen Sie es kurz darauf. |
insufficient_points | conflict | Eine Einlösung von Treuepunkten übersteigt den verfügbaren Punktestand. |
rate_limited | rate_limit | Das Anfragelimit pro Schlüssel wurde überschritten. |
maintenance_mode | server | Die Plattform befindet sich in einem Wartungsfenster. Wiederholen Sie nach dem Retry-After-Header. |
Alle Ressourcen-IDs in Veridien sind UUIDs, zum Beispiel 7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27. Die Buchungsreferenz für den Gast ist davon getrennt: confirmation_code ist ein kurzer, gut lesbarer Code (zum Beispiel B7XKQ4M2NZ), der Gästen und Personal angezeigt wird und nie als Ressourcen-ID dient. Request-IDs tragen das Präfix req_. Felder, die Sie selbst liefern, etwa payment_reference, sind für Veridien undurchsichtig und behalten das Format, das Ihr System verwendet.
POST- und PATCH-Anfragen sind die, die den Zustand ändern: einen Gast anlegen, Bestand blockieren, eine Reservierung bestätigen, Punkte einlösen, eine Gebühr buchen. Damit Wiederholungen sicher sind, senden Sie einen Idempotency-Key-Header mit einem eindeutigen Wert (eine UUID eignet sich gut):
curl -X POST https://veridien.app/api/v1/holds \
-H "Authorization: Bearer vrdn_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1d2c9a-8b3e-4a17-9c2f-1e5b7d0a4c83" \
-d '{ "room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63", "rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02", "check_in": "2026-08-01", "check_out": "2026-08-04", "guest_id": "3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34", "adults": 2 }'- Die erste Anfrage mit einem bestimmten Schlüssel läuft normal, und ihre Antwort wird gespeichert.
- Eine Wiederholung mit demselben Schlüssel und demselben Body spielt die gespeicherte Antwort ab: kein zweiter Hold, keine zweite Gebühr.
- Denselben Schlüssel mit einem anderen Body zu verwenden, liefert
409 idempotency_key_reuse. - Denselben Schlüssel gleichzeitig zu senden, bevor die erste Anfrage fertig ist, liefert
409 idempotency_in_progress. Wiederholen Sie es einen Moment später, dann erhalten Sie die gespeicherte Antwort. Der Schlüssel wird beansprucht, bevor die Operation läuft, die zweite Anfrage führt sie also nie aus. - Eine Anfrage, die fehlschlägt, gibt ihren Schlüssel frei, sodass eine ehrliche Wiederholung erneut läuft, statt den Fehlschlag abzuspielen. Nur erfolgreiche Antworten werden gespeichert: Ein
409 no_availabilitywegen einer kurzzeitigen Ausbuchung wird nicht für immer wiederholt, sobald das Zimmer wieder frei ist.
Die Schlüssel gelten je API-Schlüssel. Verwenden Sie pro logischer Operation einen frischen Idempotency-Key.
Die Bestätigung ist doppelt idempotent
Einen Hold zu bestätigen (POST /holds/{id}/confirm) ist zusätzlich idempotent auf seine payment_reference: Eine bereits bestätigte Reservierung erneut zu bestätigen oder dieselbe Zahlungsreferenz noch einmal zu senden, liefert das vorhandene bestätigte Ergebnis mit "already_confirmed": true, statt erneut zu belasten.
GET /reservations blättert mit limit und offset. Andere Listen-Endpunkte (/room-types, /services, /rate-plans) liefern den vollständigen Satz der Unterkunft und blättern nicht.
| Parameter | Standard | Max | Bedeutung |
|---|---|---|---|
limit | 25 | 100 | Wie viele Datensätze zurückgegeben werden. |
offset | 0 | 10000 | Wie viele Datensätze übersprungen werden. |
Die Antwort verpackt die Ergebnisse in data und meldet, ob noch weitere folgen:
{
"has_more": true,
"data": [ /* ... */ ]
}Für die nächste Seite addieren Sie limit auf Ihren bisherigen offset. Hören Sie auf, sobald has_more den Wert false hat.
Jeder Geldbetrag ist eine Dezimalzeichenkette, nie ein Float: "1310.40", nicht 1310.4. Parsen Sie ihn mit einem Dezimaltyp, nicht mit einem binären Fließkommatyp.
Eine Unterkunft hat eine Basiswährung, und ein Gastkonto kann gleichzeitig Zeilen in mehreren Währungen tragen (eine Zimmerrechnung in USD mit einer Restaurantzeile in MVR ist normal). Daraus folgen zwei Regeln:
Beträge in verschiedenen Währungen werden nie addiert. Überall, wo ein Saldo ausgewiesen wird, liefert ein balances-Array die tatsächlichen Werte je Währung, und das ist die Zahl, der Sie trauen sollten:
"balances": [
{ "currency": "USD", "charges": "1310.40", "payments": "0.00", "balance": "1310.40" },
{ "currency": "MVR", "charges": "1500.00", "payments": "1500.00", "balance": "0.00" }
]Ein Gastkonto ist nur dann settled, wenn in keiner Währung etwas offen ist. Eine Schuld in USD wird nie durch ein Guthaben in MVR ausgeglichen.
Pauschale Summen sind eine Bewertung und können null sein. Felder wie balance, total_charges und folio_balance sind Komfortwerte in der Basiswährung der Unterkunft, gebildet aus dem Wechselkurs, der beim Schreiben auf jeder Zeile eingefroren wurde. Weil der Kurs eingefroren ist, ändert eine spätere Kursanpassung nie den ausgewiesenen Wert einer bestehenden Gebühr. Steht eine Zeile in einer Währung, für die die Unterkunft keinen Kurs hinterlegt hat, lässt sie sich nicht bewerten, und diese Felder sind null statt einer falschen Zahl. Behandeln Sie null, bevor Sie damit rechnen.
Rate Limits arbeiten mit einem Leaky Bucket (Token Bucket), je API-Schlüssel. Ihr Eimer fasst bis zu 600 Token und füllt sich konstant mit 10 Token pro Sekunde wieder auf (600 pro Minute). Jede Anfrage verbraucht ein Token:
- Ein Burst kann den ganzen Eimer auf einmal ausschöpfen, bis zu 600 Anfragen hintereinander.
- Der Dauerdurchsatz entspricht der Nachfüllrate, 10 Anfragen pro Sekunde.
Ist der Eimer leer, liefern Anfragen 429 mit einem Retry-After-Header. Warten Sie mindestens die angegebene Anzahl Sekunden und wiederholen Sie dann. Cachen Sie Leseanfragen bevorzugt (/property, /room-types und /services tragen ein kurzes Cache-Control; /availability und /rates sind Live-Bestand und bewusst ungecacht, cachen Sie sie also auch nicht selbst) und vermeiden Sie enge Polling-Schleifen.
Zu jeder Antwort, ob Erfolg oder Fehler, gehört eine request_id (sie wird auch in Fehler-Bodies und von /me zurückgegeben). Loggen Sie sie. Wenn Sie ein Problem melden, kann der Support anhand der Request-ID genau diesen Aufruf nachverfolgen.