Ubytovačka API
Dokumentace • v1
Base URL: https://api.uby.app

Ubytovačka API (v1)

API slouží k práci s kalendářem konkrétního pokoje. Autorizace probíhá pomocí API klíče pokoje.

Stateless

Každý request nese autorizaci. Bez cookies a sessions.

Room-first

API klíč určuje kontext pokoje. Endpointy nevyžadují room_id.

Bez interních dat

API vrací jen veřejná pole a veřejná ID.

Autorizace

Každý request musí obsahovat hlavičku Authorization: Bearer s API klíčem pokoje.

HTTP Header
Authorization: Bearer {ROOM_API_KEY}
Bez hlavičky / špatný formát
HTTP 401
{"error":"missing_or_invalid_authorization"}
Neplatný klíč
HTTP 401
{"error":"invalid_api_key"}

Konvence

Identifikátor eventu

Veřejné ID eventu je UUID v poli id. V dokumentaci používáme placeholder {EVENT_ID}.

Identifikátor hosta

Veřejné ID hosta (guest) je UUID v poli id. V dokumentaci používáme placeholder {GUEST_ID}.

Datum

Formát datumu je YYYY-MM-DD. Interval je start < end.

Rozsah

Rozsah je [start, end) — check-in je start, check-out je end.

Event (public shape)
{
  "id": "{EVENT_ID}",
  "title": "Rezervace",
  "start": "2026-03-30",
  "end": "2026-04-01",
  "guests": 2,
  "external_id": "string | null"
}

external_id je volitelné externí ID (viz sekce External ID).

Poznámky k rozsahům
  • Rozsah je vždy [start, end) — check-in je start, check-out je end.
  • Overlap kontrola je start < existing_end AND end > existing_start.

External ID (integrace)

external_id je volitelné pole pro mapování objektů na ID z externího systému (např. PMS / Channel manager). API ho nikam „nepočítá“ – slouží jen pro dohledání / synchronizaci (a často i idempotenci).

Event: event.external_id
  • Posílá se v POST /events a lze měnit přes PATCH /events/{EVENT_ID}.
  • Typicky ID rezervace z externího systému (např. EXT-RES-12345).
  • Hodnota může být null.
Host: persons[].external_id
  • Volitelné pole u osoby (hosta) v persons / persons_add.
  • external_id u hosta musí být unikátní v rámci jednoho eventu.
  • Pokud dojde ke konfliktu, API vrátí 409 external_id_conflict.
  • Hodnota může být null.
Chyba: konflikt external_id
HTTP 409
{"error":"external_id_conflict","hint":"This external_id already exists in this event","fields":["persons.0.external_id"]}

Datové typy (schemas)

Tato sekce popisuje datové typy použité napříč endpointy (např. Person/host), a také konkrétní request schémata pro vybrané operace (např. POST /events).

POST /events – Request schema
Pole Typ Povinné Popis
title string ANO Název rezervace
start string (YYYY-MM-DD) ANO Datum příjezdu (check-in)
end string (YYYY-MM-DD) ANO Datum odjezdu (check-out)
guests integer (>= 1) ANO Počet hostů
persons array<Person> ANO Povinný seznam hostů. Musí obsahovat alespoň 1 položku a počet položek musí být ≤ guests. Položka je typu Person (viz níže).
external_id string | null NE Volitelné externí ID rezervace (integrace / idempotence)
Pozn.: data se validují proti meta endpointům (sex_id, category_id, document_id, purpose, country_code).
Person (host) – společný typ napříč endpointy

Typ Person se používá v různých requestech/responsech (např. POST /eventspersons[], PATCH /events/{EVENT_ID}persons_add[], a výpis hostů v GET /events/{EVENT_ID}/guests). Konkrétní povinnost polí se může lišit podle endpointu – zde je uveden tvar objektu a význam polí.

Pole Typ Povinné Popis
external_id string | null NE Externí ID hosta (unikátní v rámci eventu)
name string ANO Jméno
surname string ANO Příjmení
sex_id integer ANO Pohlaví (viz GET /meta/sex)
category_id integer ANO Kategorie (viz GET /meta/categories)
birth_date string (YYYY-MM-DD) ANO Datum narození
document_id integer ANO Typ dokladu (viz GET /meta/document-types)
document_number string ANO Číslo dokladu
street string ANO Ulice a číslo
city string ANO Město
country_code string (ISO3) ANO Stát (3 písmena, viz GET /meta/countries)
purpose integer ANO Účel pobytu (viz GET /meta/purposes)
email string | null NE E-mail hosta
phone string | null NE Telefon hosta
title string | null NE Titul
birth_place string | null NE Místo narození
zip string | null NE PSČ
visa_number string | null NE Číslo víza (pokud relevantní)
car_mark string | null NE SPZ / poznávací značka vozidla
note string | null NE Poznámka k hostovi
Pozn.: Ne všechny endpointy musí přijímat všechna volitelná pole. Pokud endpoint dané pole nepodporuje, API vrátí chybu validace / nepovolené pole. Validace vybraných polí probíhá proti meta endpointům (sex_id, category_id, document_id, purpose, country_code).

GET /events

Vrátí seznam rezervací v zadaném rozsahu. Pokud from a to nejsou uvedeny současně, použije se fallback podle monthsBack.

Query Typ Popis
from YYYY-MM-DD Začátek rozsahu (volitelné; použije se jen společně s to)
to YYYY-MM-DD Konec rozsahu (volitelné; použije se jen společně s from)
monthsBack integer Fallback režim: kolik měsíců zpět (default 2). Použije se jen když from a to nejsou oba uvedené.
Response 200
{
  "ok": true,
  "events": [
    {
      "id": "{EVENT_ID}",
      "title": "string",
      "start": "YYYY-MM-DD",
      "end": "YYYY-MM-DD",
      "guests": 2,
      "external_id": "string | null"
    }
  ]
}

external_id je volitelné externí ID rezervace (např. ID z PMS/OTA) – pro párování a idempotenci.

422 – Špatný formát datumu
HTTP 422
{"error":"invalid_date_format","hint":"Use YYYY-MM-DD"}
422 – Neplatný rozsah
HTTP 422
{"error":"invalid_date_range","hint":"`from` must be < `to`"}

POST /events

Vytvoří nový event ve stavu pre-booking v kalendáři pokoje a volitelně vytvoří hosty. Pokud jsou hosté vytvářeni, první vytvořený host je označen jako leader = 1.

Request JSON
{
  "title": "Novákovi",
  "start": "2026-04-01",
  "end": "2026-04-06",
  "guests": 3,
  "external_id": "EXT-RES-12345",
  "persons": [
    {
      "external_id": "EXT-GUEST-1",
      "name": "Jan",
      "surname": "Novák",
      "sex_id": 1,
      "category_id": 12,
      "birth_date": "1980-10-10",
      "document_id": 10,
      "document_number": "123456789",
      "street": "Evropská 1171/10",
      "city": "Praha 4",
      "country_code": "CZE",
      "purpose": 9
    }
  ]
}
Pravidla
  • persons je volitelné. Pokud je uvedeno, musí být pole (array).
  • Pokud je persons uvedeno, musí obsahovat alespoň 1 položku.
  • persons nesmí mít více položek než guests.
  • guests musí být >= 1.
  • Pokud má pokoj nastavenou kapacitu, platí limit pro guests i pro počet položek v persons.
  • Datum je YYYY-MM-DD a rozsah je start < end.
Response 201
{
  "ok": true,
  "event": {
    "id": "{EVENT_ID}",
    "title": "string",
    "start": "YYYY-MM-DD",
    "end": "YYYY-MM-DD",
    "guests": 3,
    "external_id": "EXT-RES-12345"
  },
  "persons_created": 1,
  "persons": [
    { "id": "{GUEST_ID}", "leader": 1, "external_id": "EXT-GUEST-1" }
  ]
}
Overlap
HTTP 409
{"error":"overlap","hint":"Requested date range overlaps existing event"}
Validace (chybí povinné pole)
HTTP 422
{"error":"validation_error","fields":["title","start","end"]}
Neplatný formát datumu
HTTP 422
{"error":"invalid_date_format","hint":"Use YYYY-MM-DD"}
Neplatný rozsah (start ≥ end)
HTTP 422
{"error":"invalid_date_range","hint":"`start` must be < `end`"}
Kapacita pokoje
HTTP 422
{"error":"capacity_exceeded","hint":"Room capacity is 4, requested guests is 5","fields":["guests"]}
persons je uvedeno, ale je neplatné
HTTP 422
{"error":"validation_error","fields":["persons"]}

HTTP 422
{"error":"validation_error","fields":["persons"],"hint":"If `persons` is provided, it must contain at least 1 item"}

HTTP 422
{"error":"validation_error","fields":["persons","guests"],"hint":"`persons` count must be <= `guests`"}

GET /events/{EVENT_ID}

Vrátí detail konkrétní rezervace. {EVENT_ID} je UUID z pole event.id.

Request

Bez body. Pouze URL + Authorization.

GET /v1/events/{EVENT_ID}
Authorization: Bearer {ROOM_API_KEY}
Response 200
{
  "ok": true,
  "event": {
    "id": "{EVENT_ID}",
    "title": "string",
    "start": "YYYY-MM-DD",
    "end": "YYYY-MM-DD",
    "guests": 2,
    "external_id": "string | null"
  }
}

external_id – volitelné externí ID rezervace (např. ID z PMS nebo OTA systému).

Nenalezeno
HTTP 404
{"error":"not_found"}
Chybí ID v URL
HTTP 422
{"error":"invalid_event_id"}

PATCH /events/{EVENT_ID}

Aktualizuje existující event (název/termín/počet hostů) a volitelně umožní přidat nové hosty přes persons_add. {EVENT_ID} je UUID eventu z API.

Poznámka: Úpravy jsou povolené pouze pro eventy ve stavu pre_booking.

Pravidla
  • PATCH je partial update – posíláš jen pole, která chceš změnit.
  • guests nesmí být menší než aktuální počet existujících hostů u eventu.
  • persons_add může obsahovat jen tolik položek, kolik dovolí guests a kapacita pokoje.
  • leader se přes API nenastavuje.
  • external_id (eventu) je volitelné a lze ho měnit přes PATCH. Hodnota může být null.
Request JSON (příklad)
{
  "title": "Novotní + babička",
  "external_id": "EXT-RES-12345-UPDATED",
  "guests": 3,
  "persons_add": [
    {
      "external_id": "EXT-GUEST-3",
      "name": "Marie",
      "surname": "Novotná",
      "sex_id": 2,
      "category_id": 12,
      "birth_date": "1950-05-05",
      "document_id": 10,
      "document_number": "CZ99999999",
      "street": "Květná 12",
      "city": "Brno",
      "country_code": "CZE",
      "purpose": 9
    }
  ]
}

persons_add je volitelné. Pokud se pošle, přidají se nové osoby do eventu.

Response 200
{
  "ok": true,
  "event": {
    "id": "{EVENT_ID}",
    "title": "Novotní + babička",
    "start": "2026-04-07",
    "end": "2026-04-09",
    "guests": 3,
    "external_id": "string | null"
  },
  "persons_added": 1,
  "meta": {
    "capacity": 4,
    "guests": 3,
    "persons_count": 3,
    "remaining_by_guests": 0,
    "remaining_by_capacity": 1
  }
}
403 – Jen pre-booking
HTTP 403
{"error":"forbidden","hint":"Only pre-booking events can be updated via API"}
409 – Overlap
HTTP 409
{"error":"overlap","hint":"Requested date range overlaps existing event"}
409 – Konflikt external_id (persons_add)
HTTP 409
{"error":"external_id_conflict","hint":"This external_id already exists in this event","fields":["persons_add.0.external_id"]}

Pozn.: external_id u hosta musí být unikátní v rámci jednoho eventu (rezervace).

422 – Prázdné body
HTTP 422
{"error":"validation_error","fields":["body"],"hint":"Empty JSON body"}
422 – Neplatné datum
HTTP 422
{"error":"validation_error","fields":["start","end"]}

Pozn.: v API se při špatném formátu datumu vrací validation_error (bez hintu).

422 – Neplatný rozsah (start ≥ end)
HTTP 422
{"error":"invalid_date_range","hint":"`start` must be < `end`"}
422 – Kapacita pokoje
HTTP 422
{"error":"capacity_exceeded","hint":"Room capacity is 4, requested guests is 5","fields":["guests"]}
422 – Guests je moc nízko
HTTP 422
{"error":"guests_too_low","hint":"Event already has 3 person(s), cannot set guests to 2","fields":["guests"]}
422 – Event je plný (persons_add se nevejde)
HTTP 422
{"error":"persons_exceed_guests","hint":"You can add max 0 person(s) because event is 3/3","fields":["persons_add","guests"]}
422 – Neplatné ID
HTTP 422
{"error":"invalid_event_id"}
404 – Nenalezeno
HTTP 404
{"error":"not_found"}

POST /events/{EVENT_ID}/confirm

Potvrdí pre_booking event (finalize booking). Po potvrzení už event není ve stavu pre_booking.

Request

Bez body. Pouze URL + Authorization.

POST /v1/events/{EVENT_ID}/confirm
Authorization: Bearer {ROOM_API_KEY}
Response 200
{
  "ok": true,
  "message": "confirmed",
  "event": {
    "id": "{EVENT_ID}",
    "title": "string",
    "start": "YYYY-MM-DD",
    "end": "YYYY-MM-DD",
    "guests": 2
  },
  "meta": {
    "persons_count": 2
  }
}
422 – Neplatné ID
HTTP 422
{"error":"invalid_event_id"}
404 – Nenalezeno
HTTP 404
{"error":"not_found"}
409 – Už potvrzeno
HTTP 409
{"error":"already_confirmed","hint":"Event is not in pre_booking state"}
422 – Nekonzistence persons vs guests
HTTP 422
{"error":"persons_exceed_guests","hint":"Event has 4 person(s), but guests is 3","fields":["guests"]}

DELETE /events/{EVENT_ID}

Zruší rezervaci. Po úspěšném zrušení již nebude dostupná přes API.

Request

Bez body. Pouze URL + Authorization.

DELETE /v1/events/{EVENT_ID}
Authorization: Bearer {ROOM_API_KEY}
Response 200
{
  "ok": true,
  "message": "event_deleted",
  "event_id": "{EVENT_ID}"
}
404 – Nenalezeno
HTTP 404
{"error":"not_found"}
403 – Operace nepovolena
HTTP 403
{"error":"forbidden"}
422 – Neplatné ID
HTTP 422
{"error":"invalid_event_id"}

GET /events/{EVENT_ID}/guests

Vrátí seznam hostů přiřazených ke konkrétnímu eventu. První host je vždy označen jako leader: 1.

Response 200
{
  "ok": true,
  "guests": [
    {
      "id": "{GUEST_ID}",
      "external_id": "string | null",
      "leader": 1,

      "name": "Petr",
      "surname": "Novák",
      "birth_date": "1982-03-03",
      "sex_id": 1,
      "category_id": 12,
      "country_code": "CZE",
      "document_id": 10,
      "document_number": "CZ12345678",
      "purpose": 9,

      "street": "Květná 12",
      "city": "Brno",

      "email": null,
      "phone": null,

      "title": null,
      "birth_place": null,
      "zip": null,
      "visa_number": null,
      "car_mark": null,
      "note": null
    }
  ]
}

external_id je volitelné externí ID hosta (např. ID osoby z PMS systému). Je unikátní v rámci jednoho eventu.

Některá pole mohou být null, pokud nejsou vyplněná.

404 – Nenalezeno
HTTP 404
{"error":"not_found"}
422 – Neplatné ID eventu
HTTP 422
{"error":"invalid_event_id"}

PATCH /events/{EVENT_ID}/guests/{GUEST_ID}

Upraví údaje konkrétního hosta v rámci eventu. {EVENT_ID} je UUID eventu z API, {GUEST_ID} je UUID hosta z API.

Poznámka: pole leader nelze přes API měnit.

Request JSON (partial)
{
  "email": "marie.novotna@example.com",
  "phone": "+420777123456",
  "note": "babička"
}

PATCH je “partial update” – pošlete jen pole, která chcete změnit.

Response 200
{
  "ok": true,
  "guest": {
    "id": "{GUEST_ID}",
    "leader": 0,
    "title": null,
    "name": "Marie",
    "surname": "Novotná",
    "birth_date": "1950-05-05",
    "birth_place": null,
    "sex_id": 2,
    "category_id": 12,
    "street": "Květná 12",
    "city": "Brno",
    "zip": null,
    "country_code": "CZE",
    "email": "marie.novotna@example.com",
    "phone": "+420777123456",
    "document_id": 10,
    "document_number": "CZ99999999",
    "visa_number": null,
    "purpose": 9,
    "car_mark": null,
    "note": "babička"
  }
}
404 – Nenalezeno

Event neexistuje v kontextu pokoje, nebo host nepatří do eventu.

HTTP 404
{"error":"not_found"}
422 – Prázdné body
HTTP 422
{"error":"validation_error","fields":["body"],"hint":"Empty JSON body"}
422 – Neplatné ID
HTTP 422
{"error":"invalid_event_id"} // nebo {"error":"invalid_guest_id"}
422 – Validace pole

Např. špatný e-mail, datum narození nebo kód státu.

HTTP 422
{"error":"validation_error","fields":["email"]}

HTTP 422
{"error":"validation_error","fields":["birth_date"]}

HTTP 422
{"error":"validation_error","fields":["country_code"]}
422 – leader nelze měnit
HTTP 422
{"error":"leader_immutable","hint":"Field `leader` cannot be changed via API","fields":["leader"]}
422 – Zakázané pole

Pokud se někdo pokusí měnit interní pole (např. id, hash, …).

HTTP 422
{"error":"field_not_allowed","hint":"Field `id` cannot be changed via API","fields":["id"]}

DELETE /events/{EVENT_ID}/guests/{GUEST_ID}

Odebere hosta z rezervace. Po úspěchu už host nebude dostupný přes API. Hlavního hosta (leader) nelze odebrat.

Path params
Param Typ Popis
EVENT_ID UUID ID rezervace (event)
GUEST_ID UUID ID hosta v rámci rezervace
Request

Bez body. Pouze URL + Authorization.

DELETE /v1/events/{EVENT_ID}/guests/{GUEST_ID}
Authorization: Bearer {ROOM_API_KEY}
Response 200
{
  "ok": true,
  "message": "guest_deleted",
  "event_id": "{EVENT_ID}",
  "guest_id": "{GUEST_ID}"
}
403 – Nelze odebrat hlavního hosta
HTTP 403
{"error":"leader_delete_forbidden"}
403 – Operace nepovolena
HTTP 403
{"error":"forbidden"}
404 – Nenalezeno

Event neexistuje v kontextu pokoje, nebo host nepatří do eventu.

HTTP 404
{"error":"not_found"}
422 – Neplatné ID
HTTP 422
{"error":"invalid_event_id"}
HTTP 422
{"error":"invalid_guest_id"}
Poznámka

Event i host musí patřit do stejného pokoje (určeno API klíčem) a host musí patřit do daného eventu.

POST /events/{EVENT_ID}/checkin

Odešle e-mail s odkazem na online check-in pro konkrétní event. {EVENT_ID} je UUID eventu z API.

Request JSON
{
  "email": "guest@example.com"
}
Response 200
{
  "ok": true,
  "message": "checkin_email_sent",
  "event_id": "{EVENT_ID}"
}
Validace
HTTP 422
{"error":"validation_error","fields":["email"]}
Neplatné ID
HTTP 422
{"error":"invalid_event_id"}
Nenalezeno
HTTP 404
{"error":"not_found"}
Odeslání selhalo
HTTP 500
{"error":"email_failed"}

Meta číselníky

Meta endpointy vrací seznamy validních hodnot pro vybraná pole v API (např. sex_id, document_id, category_id, purpose, country_code).

Společný formát odpovědi
{
  "ok": true,
  "items": [
    { "id": 1, "code": "optional", "name": "string" }
  ]
}
  • id se používá v requestech jako *_id (např. sex_id).
  • code může být null (pokud pro daný seznam nedává smysl).
  • U států se posílá country_code jako 3 písmena (např. CZE).

Všechny meta endpointy vyžadují autorizaci (viz sekce Autorizace) a chyby jsou popsané v Status kódy & chyby.

Validace podle meta číselníků

Některá pole v requestech musí odpovídat hodnotám z meta endpointů. Pokud pošleš neexistující ID/kód, API vrátí 422 a konkrétní error.

Pole Validace proti Error při chybě
sex_id GET /meta/sex invalid_sex_id
category_id GET /meta/categories invalid_category_id
document_id GET /meta/document-types invalid_document_id
purpose GET /meta/purposes invalid_purpose
country_code GET /meta/countries invalid_country_code
Příklad: neplatná kategorie
HTTP 422
  {"error":"invalid_category_id","fields":["persons.0.category_id"]}
Příklad: neplatný stát
HTTP 422
  {"error":"invalid_country_code","fields":["persons.0.country_code"]}

GET /meta/sex

Vrací seznam pohlaví pro pole sex_id.

cURL
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/meta/sex"
Response 200
{
  "ok": true,
  "items": [
    { "id": 1, "code": null, "name": "Muž" },
    { "id": 2, "code": null, "name": "Žena" }
  ]
}

GET /meta/document-types

Vrací seznam typů dokladů pro pole document_id.

cURL
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/meta/document-types"
Response 200
{
  "ok": true,
  "items": [
    { "id": 10, "code": null, "name": "Občanský průkaz" },
    { "id": 11, "code": null, "name": "Cestovní pas" }
  ]
}

GET /meta/categories

Vrací seznam kategorií hosta pro pole category_id.

cURL
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/meta/categories"
Response 200
{
  "ok": true,
  "items": [
    { "id": 12, "code": "adult", "name": "Dospělý" },
    { "id": 13, "code": "children", "name": "Dítě" }
  ]
}

GET /meta/purposes

Vrací seznam účelů pobytu pro pole purpose.

cURL
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/meta/purposes"
Response 200
{
  "ok": true,
  "items": [
    { "id": 1, "code": "00", "name": "ZDRAVOTNÍ" },
    { "id": 2, "code": "01", "name": "OBCHODNÍ" }
  ]
}

GET /meta/countries

Vrací seznam států pro použití v poli country_code (3 písmena, např. CZE).

cURL
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/meta/countries"
Response 200
{
  "ok": true,
  "items": [
    { "id": 1, "code": "AFG", "name": "Afghánistán" },
    { "id": 21, "code": "BEL", "name": "Belgie" },
    { "id": 73, "code": "FRA", "name": "Francie" },
    { "id": 203, "code": "CZE", "name": "Česká republika" }
  ]
}

Status kódy & chyby

HTTP error Kdy
200 Úspěch
201 Vytvořeno (POST /events)
401 missing_or_invalid_authorization Chybí hlavička Authorization nebo má špatný formát
401 invalid_api_key Neplatný API klíč
403 forbidden Operace není v aktuálním stavu objektu povolená
403 leader_delete_forbidden Nelze odebrat hlavního hosta (leader)
404 not_found Objekt neexistuje nebo nepatří do pokoje daného API klíčem
405 method_not_allowed Nepodporovaná HTTP metoda pro daný endpoint
409 overlap Požadovaný termín se překrývá s existující rezervací
409 already_confirmed Rezervace už je potvrzená (akci nelze provést znovu)
409 external_id_conflict Kolize external_id (typicky host v rámci jednoho eventu)
422 invalid_sex_id Neplatné sex_id (viz meta)
422 invalid_category_id Neplatné category_id (viz meta)
422 invalid_document_id Neplatné document_id (viz meta)
422 invalid_purpose Neplatný purpose (viz meta)
422 invalid_country_code Neplatný country_code (viz meta)
422 invalid_date_format Datum není ve formátu YYYY-MM-DD
422 invalid_date_range Neplatný rozsah: start < end
422 invalid_event_id Chybí nebo je prázdné {EVENT_ID} v URL
422 invalid_guest_id Chybí nebo je prázdné {GUEST_ID} v URL
422 validation_error Chybný payload (např. chybí povinné pole nebo má špatný formát).
POST /events: guests musí být >= 1 (fields: ["guests"] + hint).
POST /events: pokud je persons uvedeno, musí být pole (array) (fields: ["persons"]).
POST /events: pokud je persons uvedeno, musí obsahovat alespoň 1 položku (fields: ["persons"] + hint).
POST /events: počet položek v persons musí být <= guests (fields: ["persons","guests"] + hint).
422 capacity_exceeded Překročený maximální počet hostů pro pokoj
422 guests_too_low Nelze nastavit menší počet hostů, než kolik je už u rezervace evidováno
422 persons_exceed_guests Nelze přidat další hosty – rezervace je už plná
422 leader_immutable PATCH guest: pole leader nelze měnit
422 field_not_allowed PATCH guest: pokus o změnu interního pole (např. id, hash, order_hash, calendar_hash, deleted, …)
500 room_missing_order POST /events: room nemá přiřazenou objednávku (neočekávaný stav)
500 order_not_found POST /events: objednávka nebyla nalezena (neočekávaný stav)
500 order_hash_missing POST /events: chybí order_hash (neočekávaný stav)
500 room_context_missing Server nedokázal určit kontext pokoje (neočekávaná chyba)
500 email_failed Selhalo odeslání e-mailu (POST /events/{EVENT_ID}/checkin)
Formát chyby
{
  "error": "string",
  "hint": "string (optional)",
  "fields": ["field1","field2"] (optional)
}
Poznámka

not_found u rezervací znamená, že rezervace buď neexistuje, nebo nepatří do pokoje daného API klíčem. Díky tomu nejde “hádat” cizí rezervace.

cURL příklady

Níže jsou praktické ukázky volání API. V příkladech používáme placeholdery {EVENT_ID} a {GUEST_ID}.

Co je external_id (doporučeno pro integrace)

external_id je volitelné pole pro mapování objektů na ID z externího systému (PMS / Channel manager / OTA). API ho nijak „nepočítá“ – slouží jen pro dohledání / synchronizaci a idempotenci.

  • event.external_id – typicky ID rezervace z externího systému. Lze poslat při POST /events a měnit přes PATCH /events/{EVENT_ID}.
  • persons[].external_id / persons_add[].external_id – typicky ID osoby v externím systému. Musí být unikátní v rámci jednoho eventu, jinak API vrací 409 external_id_conflict.
  • Hodnota může být null.
Příklad konfliktu external_id
HTTP 409
{"error":"external_id_conflict","hint":"This external_id already exists in this event","fields":["persons.0.external_id"]}
Nastavit klíč do proměnné
export UBY_API_KEY="YOUR_ROOM_API_KEY"
Neplatný klíč
curl -i \
  -H "Authorization: Bearer invalid" \
  "https://api.uby.app/v1/events"
GET /events (rozsah)
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/events?from=2026-02-01&to=2026-03-31"
GET /events/{EVENT_ID}
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/events/{EVENT_ID}"
POST /events (vytvoření)
curl -i -X POST \
  -H "Authorization: Bearer $UBY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title":"Novákovi",
    "start":"2026-04-01",
    "end":"2026-04-06",
    "guests":2,
    "external_id":"EXT-RES-12345",
    "persons":[
      {
        "external_id":"EXT-GUEST-1",
        "name":"Jan",
        "surname":"Novák",
        "sex_id":1,
        "category_id":12,
        "birth_date":"1980-10-10",
        "document_id":10,
        "document_number":"123456789",
        "street":"Evropská 1171/10",
        "city":"Praha 4",
        "country_code":"CZE",
        "purpose":9
      }
    ]
  }' \
  "https://api.uby.app/v1/events"
Response 201
{
  "ok": true,
  "event": {
    "id": "{EVENT_ID}",
    "title": "Novákovi",
    "start": "2026-04-01",
    "end": "2026-04-06",
    "guests": 2,
    "external_id": "EXT-RES-12345"
  },
  "persons_created": 1,
  "persons": [
    { "id": "{GUEST_ID}", "leader": 1, "external_id": "EXT-GUEST-1" }
  ]
}
GET /events/{EVENT_ID}/guests
curl -s \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/events/{EVENT_ID}/guests"
PATCH /events/{EVENT_ID} – změna external_id + přidání hosta (persons_add)
curl -i -X PATCH \
  -H "Authorization: Bearer $UBY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id":"EXT-RES-12345-UPDATED",
    "persons_add":[
      {
        "external_id":"EXT-GUEST-2",
        "name":"Karel",
        "surname":"Novotný",
        "sex_id":1,
        "category_id":12,
        "birth_date":"1990-01-01",
        "document_id":10,
        "document_number":"CZ11111111",
        "street":"Květná 12",
        "city":"Brno",
        "country_code":"CZE",
        "purpose":9
      }
    ]
  }' \
  "https://api.uby.app/v1/events/{EVENT_ID}"
Response 200
{
  "ok": true,
  "event": {
    "id": "{EVENT_ID}",
    "title": "Novákovi",
    "start": "2026-04-01",
    "end": "2026-04-06",
    "guests": 2,
    "external_id": "EXT-RES-12345-UPDATED"
  },
  "persons_added": 1
}
PATCH /events/{EVENT_ID} – pokus o přidání hosta, když je rezervace plná
curl -i -X PATCH \
  -H "Authorization: Bearer $UBY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "persons_add":[
      {
        "name":"Karel",
        "surname":"Novotný",
        "sex_id":1,
        "category_id":12,
        "birth_date":"1990-01-01",
        "document_id":10,
        "document_number":"CZ11111111",
        "street":"Květná 12",
        "city":"Brno",
        "country_code":"CZE",
        "purpose":9
      }
    ]
  }' \
  "https://api.uby.app/v1/events/{EVENT_ID}"
Response 422
{
  "error":"persons_exceed_guests",
  "hint":"You can add max 0 person(s) because event is 2/2",
  "fields":["persons_add","guests"]
}
PATCH /events/{EVENT_ID}/guests/{guest_id}
curl -i -X PATCH \
  -H "Authorization: Bearer $UBY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email":"marie.novotna@example.com",
    "phone":"+420777123456",
    "note":"babička"
  }' \
  "https://api.uby.app/v1/events/{EVENT_ID}/guests/{GUEST_ID}"
POST /events/{EVENT_ID}/checkin
curl -i -X POST \
  -H "Authorization: Bearer $UBY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"guest@example.com"}' \
  "https://api.uby.app/v1/events/{EVENT_ID}/checkin"
DELETE /events/{EVENT_ID}/guests/{guest_id}
curl -i -X DELETE \
  -H "Authorization: Bearer $UBY_API_KEY" \
  "https://api.uby.app/v1/events/{EVENT_ID}/guests/{GUEST_ID}"